@@ -21,15 +21,12 @@ import (
2121 "time"
2222
2323 "github.com/go-logr/logr"
24- "github.com/prometheus/client_golang/prometheus"
2524 apierrors "k8s.io/apimachinery/pkg/api/errors"
2625 "k8s.io/apimachinery/pkg/api/meta"
2726 metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
2827 "k8s.io/apimachinery/pkg/runtime/schema"
29- "k8s.io/client-go/dynamic"
3028 ctrl "sigs.k8s.io/controller-runtime"
3129
32- "github.com/kro-run/kro/api/v1alpha1"
3330 kroclient "github.com/kro-run/kro/pkg/client"
3431 "github.com/kro-run/kro/pkg/graph"
3532 "github.com/kro-run/kro/pkg/metadata"
@@ -88,8 +85,6 @@ type Controller struct {
8885 // reconcileConfig holds the configuration parameters for the reconciliation
8986 // process.
9087 reconcileConfig ReconcileConfig
91- // defaultServiceAccounts is a map of service accounts to use for controller impersonation.
92- defaultServiceAccounts map [string ]string
9388}
9489
9590// NewController creates a new Controller instance.
@@ -100,17 +95,15 @@ func NewController(
10095 rgd * graph.Graph ,
10196 clientSet kroclient.SetInterface ,
10297 restMapper meta.RESTMapper ,
103- defaultServiceAccounts map [string ]string ,
10498 instanceLabeler metadata.Labeler ,
10599) * Controller {
106100 return & Controller {
107- log : log ,
108- gvr : gvr ,
109- clientSet : clientSet ,
110- rgd : rgd ,
111- instanceLabeler : instanceLabeler ,
112- reconcileConfig : reconcileConfig ,
113- defaultServiceAccounts : defaultServiceAccounts ,
101+ log : log ,
102+ gvr : gvr ,
103+ clientSet : clientSet ,
104+ rgd : rgd ,
105+ instanceLabeler : instanceLabeler ,
106+ reconcileConfig : reconcileConfig ,
114107 }
115108}
116109
@@ -145,17 +138,10 @@ func (c *Controller) Reconcile(ctx context.Context, req ctrl.Request) error {
145138 return fmt .Errorf ("failed to create instance sub-resources labeler: %w" , err )
146139 }
147140
148- // If possible, use a service account to create the execution client
149- // TODO(a-hilaly): client caching
150- executionClient , err := c .getExecutionClient (namespace )
151- if err != nil {
152- return fmt .Errorf ("failed to create execution client: %w" , err )
153- }
154-
155141 instanceGraphReconciler := & instanceGraphReconciler {
156142 log : log ,
157143 gvr : c .gvr ,
158- client : executionClient ,
144+ client : c . clientSet . Dynamic () ,
159145 restMapper : c .clientSet .RESTMapper (),
160146 runtime : rgRuntime ,
161147 instanceLabeler : c .instanceLabeler ,
@@ -177,98 +163,3 @@ func getNamespaceName(req ctrl.Request) (string, string) {
177163 }
178164 return namespace , name
179165}
180-
181- // errorCategory helps classify different types of impersonation errors
182- type errorCategory string
183-
184- const (
185- errorConfigCreate errorCategory = "config_create"
186- errorInvalidSA errorCategory = "invalid_sa"
187- errorClientCreate errorCategory = "client_create"
188- errorPermissions errorCategory = "permissions"
189- )
190-
191- // getExecutionClient determines the execution client to use for the instance.
192- // If the instance is created in a namespace of which a service account is specified,
193- // the execution client will be created using the service account. If no service account
194- // is specified for the namespace, the default client will be used.
195- func (c * Controller ) getExecutionClient (namespace string ) (dynamic.Interface , error ) {
196- // if no service accounts are specified, use the default client
197- if len (c .defaultServiceAccounts ) == 0 {
198- c .log .V (1 ).Info ("no service accounts configured, using default client" )
199- return c .clientSet .Dynamic (), nil
200- }
201-
202- timer := prometheus .NewTimer (impersonationDuration .WithLabelValues (namespace , "" ))
203- defer timer .ObserveDuration ()
204-
205- // Check for namespace specific service account
206- if sa , ok := c .defaultServiceAccounts [namespace ]; ok {
207- userName , err := getServiceAccountUserName (namespace , sa )
208- if err != nil {
209- c .handleImpersonateError (namespace , sa , err )
210- return nil , fmt .Errorf ("invalid service account configuration: %w" , err )
211- }
212-
213- pivotedClient , err := c .clientSet .WithImpersonation (userName )
214- if err != nil {
215- c .handleImpersonateError (namespace , sa , err )
216- return nil , fmt .Errorf ("failed to create impersonated client: %w" , err )
217- }
218-
219- impersonationTotal .WithLabelValues (namespace , sa , "success" ).Inc ()
220- return pivotedClient .Dynamic (), nil
221- }
222-
223- // Check for default service account (marked by "*")
224- if defaultSA , ok := c .defaultServiceAccounts [v1alpha1 .DefaultServiceAccountKey ]; ok {
225- userName , err := getServiceAccountUserName (namespace , defaultSA )
226- if err != nil {
227- c .handleImpersonateError (namespace , defaultSA , err )
228- return nil , fmt .Errorf ("invalid default service account configuration: %w" , err )
229- }
230-
231- pivotedClient , err := c .clientSet .WithImpersonation (userName )
232- if err != nil {
233- c .handleImpersonateError (namespace , defaultSA , err )
234- return nil , fmt .Errorf ("failed to create impersonated client with default SA: %w" , err )
235- }
236-
237- impersonationTotal .WithLabelValues (namespace , defaultSA , "success" ).Inc ()
238- return pivotedClient .Dynamic (), nil
239- }
240-
241- impersonationTotal .WithLabelValues (namespace , "" , "default" ).Inc ()
242- // Fallback to the default client
243- return c .clientSet .Dynamic (), nil
244- }
245-
246- // handleImpersonateError logs the error and records the error in the metrics
247- func (c * Controller ) handleImpersonateError (namespace , sa string , err error ) {
248- var category errorCategory
249- switch {
250- case strings .Contains (err .Error (), "forbidden" ):
251- category = errorPermissions
252- case strings .Contains (err .Error (), "cannot get token" ):
253- category = errorConfigCreate
254- default :
255- category = errorClientCreate
256- }
257- recordImpersonateError (namespace , sa , category )
258- c .log .Error (
259- err ,
260- "failed to create impersonated client" ,
261- "namespace" , namespace ,
262- "serviceAccount" , sa ,
263- "errorCategory" , category ,
264- )
265- }
266-
267- // getServiceAccountUserName builds the impersonate service account user name.
268- // The format of the user name is "system:serviceaccount:<namespace>:<serviceaccount>"
269- func getServiceAccountUserName (namespace , serviceAccount string ) (string , error ) {
270- if namespace == "" || serviceAccount == "" {
271- return "" , fmt .Errorf ("namespace and service account must be provided" )
272- }
273- return fmt .Sprintf ("system:serviceaccount:%s:%s" , namespace , serviceAccount ), nil
274- }
0 commit comments