From e2092b0b75ccda91382bcaffc2c01d41f92c351b Mon Sep 17 00:00:00 2001 From: Leo Li Date: Wed, 15 Nov 2023 08:20:06 -0500 Subject: [PATCH 01/62] Add the task planning toughts to the PR --- pkg/adapter/apiserver/delegate.go | 27 ++++++++++++++++++++++++++- pkg/kncloudevents/event_dispatcher.go | 1 + 2 files changed, 27 insertions(+), 1 deletion(-) diff --git a/pkg/adapter/apiserver/delegate.go b/pkg/adapter/apiserver/delegate.go index e45d87e67ae..f1f595e529e 100644 --- a/pkg/adapter/apiserver/delegate.go +++ b/pkg/adapter/apiserver/delegate.go @@ -18,7 +18,6 @@ package apiserver import ( "context" - cloudevents "github.com/cloudevents/sdk-go/v2" "github.com/google/uuid" "go.uber.org/zap" @@ -75,6 +74,32 @@ func (a *resourceDelegate) sendCloudEvent(ctx context.Context, event cloudevents subject := event.Context.GetSubject() a.logger.Debugf("sending cloudevent id: %s, source: %s, subject: %s", event.ID(), source, subject) + // Decide whether to request the JWT token or not + // Condition: if the sink has audience or not + // ?? Question: where can we get the sink audience? As we don't specify the destination in the cloudevent + + // If the sink has audience, then we need to request the JWT token + // In order to request the JWT token, we need to get the service account name and namespace from the sink + // And also need to pass in OIDC token provider + // ?? Question again: where can we get the sink audience? And how to pass in OIDC token provider? + + // If the sink doesn't have audience, then we don't need to request the JWT token + + // If the sink has audience, and we have the JWT token, then we need to add the JWT token to the cloudevent + // Easy to do this, just add the JWT token as the bearer auth header to the cloudevent header + + // Discovery: + // ReceiveAdapter -> ResourceDelegate -> MakeAddEvent -> MakeEvent -> MakeCloudEvent -> SendCloudEvent + // Receive adapter is the entry point of the adapter, it receives the k8s api event + // ResourceDelegate is the cache.Store, it receives the k8s api event from the receive adapter + + //ApiServerSource will listen to the k8s api event, and then send the cloudevent to the sink when the k8s api event is created, updated or deleted + + // Prepare the headers + //headers := http.HeaderFrom(ctx) + //jwt := auth.GetJWT(ctx) + //headers.Set("Authentication", fmt.Print("Bearer %s", jwt)) + if result := a.ce.Send(ctx, event); !cloudevents.IsACK(result) { a.logger.Errorw("failed to send cloudevent", zap.Error(result), zap.String("source", source), zap.String("subject", subject), zap.String("id", event.ID())) diff --git a/pkg/kncloudevents/event_dispatcher.go b/pkg/kncloudevents/event_dispatcher.go index 442b6125215..7385747d993 100644 --- a/pkg/kncloudevents/event_dispatcher.go +++ b/pkg/kncloudevents/event_dispatcher.go @@ -343,6 +343,7 @@ func (d *Dispatcher) createRequest(ctx context.Context, message binding.Message, request.Header[key] = val } + // saw something interesting here, it is similar to what we want to do in this PR if oidcServiceAccount != nil { if target.Audience != nil && *target.Audience != "" { jwt, err := d.oidcTokenProvider.GetJWT(*oidcServiceAccount, *target.Audience) From 48c349f6ea8aafc73b78b2766d47f20942a44956 Mon Sep 17 00:00:00 2001 From: Leo Li Date: Wed, 15 Nov 2023 15:39:56 -0500 Subject: [PATCH 02/62] add the auth header to all the send and request to the adapter --- pkg/adapter/v2/cloudevents.go | 41 +++++++++++++++++++++++++++++++++++ pkg/adapter/v2/config.go | 10 +++++++++ pkg/adapter/v2/main.go | 1 + 3 files changed, 52 insertions(+) diff --git a/pkg/adapter/v2/cloudevents.go b/pkg/adapter/v2/cloudevents.go index bce437e152f..2e43c1708d8 100644 --- a/pkg/adapter/v2/cloudevents.go +++ b/pkg/adapter/v2/cloudevents.go @@ -20,6 +20,8 @@ import ( "context" "errors" "fmt" + "k8s.io/apimachinery/pkg/types" + "knative.dev/eventing/pkg/auth" nethttp "net/http" "net/url" "time" @@ -105,6 +107,7 @@ func NewCloudEventsClientCRStatus(env EnvConfigAccessor, reporter source.StatsRe } type ClientConfig struct { + Context context.Context Env EnvConfigAccessor CeOverrides *duckv1.CloudEventOverrides Reporter source.StatsReporter @@ -195,6 +198,8 @@ func NewClient(cfg ClientConfig) (Client, error) { ceOverrides: ceOverrides, reporter: cfg.Reporter, crStatusEventClient: cfg.CrStatusEventClient, + oidcTokenProvider: auth.NewOIDCTokenProvider(cfg.Context), + audience: cfg.Env.GetAudience(), }, nil } @@ -217,6 +222,10 @@ type client struct { reporter source.StatsReporter crStatusEventClient *crstatusevent.CRStatusEventClient closeIdler closeIdler + + oidcTokenProvider *auth.OIDCTokenProvider + audience *string + serviceAccountName types.NamespacedName } func (c *client) CloseIdleConnections() { @@ -228,6 +237,22 @@ var _ cloudevents.Client = (*client)(nil) // Send implements client.Send func (c *client) Send(ctx context.Context, out event.Event) protocol.Result { c.applyOverrides(&out) + + // If the sink has audience, then we need to request the JWT token + if c.audience != nil { + // Request the JWT token for the given service account + jwt, err := c.oidcTokenProvider.GetJWT(c.serviceAccountName, *c.audience) + + if err != nil { + return protocol.NewResult("%w", err) + } + + // Appending the auth token to the outgoing request + headers := http.HeaderFrom(ctx) + headers.Set("Authentication", fmt.Sprintf("Bearer %s", jwt)) + ctx = http.WithCustomHeader(ctx, headers) + } + res := c.ceClient.Send(ctx, out) c.reportMetrics(ctx, out, res) return res @@ -236,6 +261,22 @@ func (c *client) Send(ctx context.Context, out event.Event) protocol.Result { // Request implements client.Request func (c *client) Request(ctx context.Context, out event.Event) (*event.Event, protocol.Result) { c.applyOverrides(&out) + + // If the sink has audience, then we need to request the JWT token + if c.audience != nil { + // Request the JWT token for the given service account + jwt, err := c.oidcTokenProvider.GetJWT(c.serviceAccountName, *c.audience) + + if err != nil { + return nil, protocol.NewResult("%w", err) + } + + // Appending the auth token to the outgoing request + headers := http.HeaderFrom(ctx) + headers.Set("Authentication", fmt.Sprintf("Bearer %s", jwt)) + ctx = http.WithCustomHeader(ctx, headers) + } + resp, res := c.ceClient.Request(ctx, out) c.reportMetrics(ctx, out, res) return resp, res diff --git a/pkg/adapter/v2/config.go b/pkg/adapter/v2/config.go index d4d54ba76e4..6386b38e6ea 100644 --- a/pkg/adapter/v2/config.go +++ b/pkg/adapter/v2/config.go @@ -66,6 +66,9 @@ type EnvConfig struct { // Sink is the URI messages will be sent. Sink string `envconfig:"K_SINK"` + // Audience is the audience of the target sink. + Audience *string `envconfig:"K_AUDIENCE"` + // CACerts are the Certification Authority (CA) certificates in PEM format // according to https://www.rfc-editor.org/rfc/rfc7468. // +optional @@ -113,6 +116,9 @@ type EnvConfigAccessor interface { // GetCACerts gets the CACerts of the Sink. GetCACerts() *string + // Get the audience of the target sink. + GetAudience() *string + // Get the namespace of the adapter. GetNamespace() string @@ -176,6 +182,10 @@ func (e *EnvConfig) GetCACerts() *string { return e.CACerts } +func (e *EnvConfig) GetAudience() *string { + return e.Audience +} + func (e *EnvConfig) GetNamespace() string { return e.Namespace } diff --git a/pkg/adapter/v2/main.go b/pkg/adapter/v2/main.go index a839cd66896..217482151c4 100644 --- a/pkg/adapter/v2/main.go +++ b/pkg/adapter/v2/main.go @@ -215,6 +215,7 @@ func MainWithInformers(ctx context.Context, component string, env EnvConfigAcces } clientConfig := ClientConfig{ + Context: ctx, Env: env, Reporter: reporter, CrStatusEventClient: crStatusEventClient, From e7b38a82f58c87b3ef3c401b8b48745c5999b9a9 Mon Sep 17 00:00:00 2001 From: Leo Li Date: Mon, 20 Nov 2023 09:13:26 -0500 Subject: [PATCH 03/62] Adding the env var for K_AUDIENCE --- pkg/reconciler/apiserversource/apiserversource.go | 1 + pkg/reconciler/apiserversource/resources/receive_adapter.go | 4 ++++ 2 files changed, 5 insertions(+) diff --git a/pkg/reconciler/apiserversource/apiserversource.go b/pkg/reconciler/apiserversource/apiserversource.go index a9c34523232..0ed020ec864 100644 --- a/pkg/reconciler/apiserversource/apiserversource.go +++ b/pkg/reconciler/apiserversource/apiserversource.go @@ -210,6 +210,7 @@ func (r *Reconciler) createReceiveAdapter(ctx context.Context, src *v1.ApiServer Labels: resources.Labels(src.Name), CACerts: sinkAddr.CACerts, SinkURI: sinkAddr.URL.String(), + Audience: sinkAddr.Audience, Configs: r.configs, Namespaces: namespaces, AllNamespaces: allNamespaces, diff --git a/pkg/reconciler/apiserversource/resources/receive_adapter.go b/pkg/reconciler/apiserversource/resources/receive_adapter.go index b7f1bd5363a..33ef12106d9 100644 --- a/pkg/reconciler/apiserversource/resources/receive_adapter.go +++ b/pkg/reconciler/apiserversource/resources/receive_adapter.go @@ -44,6 +44,7 @@ type ReceiveAdapterArgs struct { Image string Source *v1.ApiServerSource Labels map[string]string + Audience *string SinkURI string CACerts *string Configs reconcilersource.ConfigAccessor @@ -153,6 +154,9 @@ func makeEnv(args *ReceiveAdapterArgs) ([]corev1.EnvVar, error) { envs := []corev1.EnvVar{{ Name: adapter.EnvConfigSink, Value: args.SinkURI, + }, { + Name: "K_AUDIENCE", + Value: *args.Audience, }, { Name: "K_SOURCE_CONFIG", Value: config, From 8efcee8f72a96ba29c05573c87ad032e825c5b13 Mon Sep 17 00:00:00 2001 From: Leo Li Date: Mon, 20 Nov 2023 09:13:52 -0500 Subject: [PATCH 04/62] Adding the rekt test --- test/auth/features/oidc/apiserversource.go | 104 +++++++++++++++++++++ test/auth/oidc_test.go | 17 ++++ 2 files changed, 121 insertions(+) create mode 100644 test/auth/features/oidc/apiserversource.go diff --git a/test/auth/features/oidc/apiserversource.go b/test/auth/features/oidc/apiserversource.go new file mode 100644 index 00000000000..99bc5dcdf0f --- /dev/null +++ b/test/auth/features/oidc/apiserversource.go @@ -0,0 +1,104 @@ +/* +Copyright 2023 The Knative Authors + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package oidc + +import ( + "context" + "github.com/cloudevents/sdk-go/v2/test" + rbacv1 "k8s.io/api/rbac/v1" + v1 "knative.dev/eventing/pkg/apis/sources/v1" + "knative.dev/eventing/test/rekt/features/featureflags" + "knative.dev/eventing/test/rekt/features/source" + "knative.dev/eventing/test/rekt/resources/account_role" + "knative.dev/eventing/test/rekt/resources/apiserversource" + "knative.dev/reconciler-test/pkg/eventshub" + eventasssert "knative.dev/reconciler-test/pkg/eventshub/assert" + "knative.dev/reconciler-test/pkg/feature" + "knative.dev/reconciler-test/pkg/manifest" + "knative.dev/reconciler-test/pkg/resources/pod" + "knative.dev/reconciler-test/pkg/resources/service" +) + +const ( + exampleImage = "ko://knative.dev/eventing/test/test_images/print" +) + +func ApiserversourceSendEventWithJWT() *feature.Feature { + src := feature.MakeRandomK8sName("apiserversource") + sink := feature.MakeRandomK8sName("sink") + audience := "my-sink-audience" + sacmName := feature.MakeRandomK8sName("apiserversource") + + f := feature.NewFeatureNamed("Send events to TLS sink") + + f.Prerequisite("should not run when Istio is enabled", featureflags.IstioDisabled()) + f.Prerequisite("transport encryption is strict", featureflags.TransportEncryptionStrict()) + + f.Setup("deploy receiver", eventshub.Install(sink, + eventshub.StartReceiver, + eventshub.OIDCReceiverAudience(audience))) + + f.Setup("Create Service Account for ApiServerSource with RBAC for v1.Event resources", + setupAccountAndRoleForPods(sacmName)) + + cfg := []manifest.CfgFn{ + apiserversource.WithServiceAccountName(sacmName), + apiserversource.WithEventMode(v1.ResourceMode), + apiserversource.WithResources(v1.APIVersionKindSelector{ + APIVersion: "v1", + Kind: "Event", + }), + } + + f.Requirement("install ApiServerSource", func(ctx context.Context, t feature.T) { + d := service.AsDestinationRef(sink) + d.CACerts = eventshub.GetCaCerts(ctx) + + cfg = append(cfg, apiserversource.WithSink(d)) + apiserversource.Install(src, cfg...)(ctx, t) + }) + f.Requirement("ApiServerSource goes ready", apiserversource.IsReady(src)) + + examplePodName := feature.MakeRandomK8sName("example") + // create a pod so that ApiServerSource delivers an event to its sink + // event body is similar to this: + // {"kind":"Pod","namespace":"test-wmbcixlv","name":"example-axvlzbvc","apiVersion":"v1"} + f.Requirement("install example pod", pod.Install(examplePodName, exampleImage)) + + f.Stable("ApiServerSource as event source"). + Must("delivers events on sink with ref", + eventasssert.OnStore(sink). + Match(eventasssert.MatchKind(eventshub.EventReceived)). + MatchEvent(test.HasType("dev.knative.apiserver.resource.update")). + AtLeast(1), + ). + Must("Set sinkURI to HTTPS endpoint", source.ExpectHTTPSSink(apiserversource.Gvr(), src)). + Must("Set sinkCACerts to non empty CA certs", source.ExpectCACerts(apiserversource.Gvr(), src)) + + return f +} + +func setupAccountAndRoleForPods(sacmName string) feature.StepFn { + return account_role.Install(sacmName, + account_role.WithRole(sacmName+"-clusterrole"), + account_role.WithRules(rbacv1.PolicyRule{ + APIGroups: []string{""}, + Resources: []string{"events", "pods"}, + Verbs: []string{"get", "list", "watch"}, + }), + ) +} diff --git a/test/auth/oidc_test.go b/test/auth/oidc_test.go index 211a7c1d829..ea6d6b66a94 100644 --- a/test/auth/oidc_test.go +++ b/test/auth/oidc_test.go @@ -37,6 +37,7 @@ import ( "knative.dev/eventing/test/rekt/resources/channel_impl" "knative.dev/eventing/test/rekt/resources/channel_template" "knative.dev/eventing/test/rekt/resources/parallel" + "knative.dev/reconciler-test/pkg/eventshub" ) func TestBrokerSupportsOIDC(t *testing.T) { @@ -95,3 +96,19 @@ func TestParallelSupportsOIDC(t *testing.T) { env.Test(ctx, t, oidc.ParallelHasAudienceOfInputChannel(name, env.Namespace(), channel_impl.GVR(), channel_impl.GVK().Kind)) } + +func TestApiserversourceSendEventWithJWT(t *testing.T) { + t.Parallel() + + ctx, env := global.Environment( + knative.WithKnativeNamespace(system.Namespace()), + knative.WithLoggingConfig, + knative.WithTracingConfig, + k8s.WithEventListener, + environment.Managed(t), + eventshub.WithTLS(t), + environment.WithPollTimings(4*time.Second, 12*time.Minute), + ) + + env.Test(ctx, t, oidc.ApiserversourceSendEventWithJWT()) +} From e11c5e96e83b916d15ad3ebde8096df9fd6a35b3 Mon Sep 17 00:00:00 2001 From: Leo Li Date: Fri, 24 Nov 2023 08:37:28 -0500 Subject: [PATCH 05/62] Adding the rolebinding for create_oidc Signed-off-by: Leo Li --- pkg/auth/serviceaccount.go | 100 ++++++++++++++++++ .../apiserversource/resources/role_binding.go | 46 ++++++++ .../controller/resources/role_binding.go | 2 +- 3 files changed, 147 insertions(+), 1 deletion(-) create mode 100644 pkg/reconciler/apiserversource/resources/role_binding.go diff --git a/pkg/auth/serviceaccount.go b/pkg/auth/serviceaccount.go index c73064bb9b1..4c811892945 100644 --- a/pkg/auth/serviceaccount.go +++ b/pkg/auth/serviceaccount.go @@ -19,6 +19,7 @@ package auth import ( "context" "fmt" + rbacv1 "k8s.io/api/rbac/v1" "strings" "go.uber.org/zap" @@ -94,3 +95,102 @@ func EnsureOIDCServiceAccountExistsForResource(ctx context.Context, serviceAccou return nil } + +// EnsureOIDCServiceAccountRoleBindingExistsForResource +// makes sure the given resource has an OIDC service account role binding with +// an owner reference to the resource set. +func EnsureOIDCServiceAccountRoleBindingExistsForResource(ctx context.Context, kubeclient kubernetes.Interface, gvk schema.GroupVersionKind, objectMeta metav1.ObjectMeta) error { + roleName := fmt.Sprintf("create-oidc-token") + roleBindingName := fmt.Sprintf("create-oidc-token", objectMeta.GetName()) + roleBinding, err := kubeclient.RbacV1().RoleBindings(objectMeta.Namespace).Get(ctx, roleBindingName, metav1.GetOptions{}) + + // If the resource doesn't exist, we'll create it. + if apierrs.IsNotFound(err) { + logging.FromContext(ctx).Debugw("Creating OIDC service account role binding", zap.Error(err)) + + // Create the "create-oidc-token" role + CreateRoleForServiceAccount(ctx, kubeclient, gvk, objectMeta) + + roleBinding := &rbacv1.RoleBinding{ + ObjectMeta: metav1.ObjectMeta{ + Name: roleBindingName, + Namespace: objectMeta.GetNamespace(), + Annotations: map[string]string{ + "description": fmt.Sprintf("Role Binding for OIDC Authentication for %s %q", gvk.GroupKind().Kind, objectMeta.Name), + }, + }, + RoleRef: rbacv1.RoleRef{ + APIGroup: "rbac.authorization.k8s.io", + Kind: "Role", + Name: roleName, + }, + Subjects: []rbacv1.Subject{ + { + Kind: "ServiceAccount", + Namespace: objectMeta.GetNamespace(), + Name: GetOIDCServiceAccountNameForResource(gvk, objectMeta), + }, + }, + } + + _, err = kubeclient.RbacV1().RoleBindings(objectMeta.Namespace).Create(ctx, roleBinding, metav1.CreateOptions{}) + if err != nil { + return fmt.Errorf("could not create OIDC service account role binding %s/%s for %s: %w", objectMeta.Name, objectMeta.Namespace, gvk.Kind, err) + } + + return nil + } + + if err != nil { + return fmt.Errorf("could not get OIDC service account role binding %s/%s for %s: %w", objectMeta.Name, objectMeta.Namespace, gvk.Kind, err) + + } + + if !metav1.IsControlledBy(&roleBinding.ObjectMeta, &objectMeta) { + return fmt.Errorf("role binding %s not owned by %s %s", roleBinding.Name, gvk.Kind, objectMeta.Name) + } + + return nil +} + +// Create the create-oidc-token role for the service account +func CreateRoleForServiceAccount(ctx context.Context, kubeclient kubernetes.Interface, gvk schema.GroupVersionKind, objectMeta metav1.ObjectMeta) error { + roleName := fmt.Sprintf("create-oidc-token") + role, err := kubeclient.RbacV1().Roles(objectMeta.Namespace).Get(ctx, roleName, metav1.GetOptions{}) + + // If the resource doesn't exist, we'll create it. + if apierrs.IsNotFound(err) && role == nil { + logging.FromContext(ctx).Debugw("Creating OIDC service account role", zap.Error(err)) + + role := &rbacv1.Role{ + ObjectMeta: metav1.ObjectMeta{ + Name: roleName, + Namespace: objectMeta.GetNamespace(), + Annotations: map[string]string{ + "description": fmt.Sprintf("Role for OIDC Authentication for %s %q", gvk.GroupKind().Kind, objectMeta.Name), + }, + }, + Rules: []rbacv1.PolicyRule{ + rbacv1.PolicyRule{ + APIGroups: []string{""}, + ResourceNames: []string{objectMeta.Name}, + Resources: []string{"serviceaccounts/token"}, + Verbs: []string{"create"}, + }, + }, + } + + _, err = kubeclient.RbacV1().Roles(objectMeta.Namespace).Create(ctx, role, metav1.CreateOptions{}) + if err != nil { + return fmt.Errorf("could not create OIDC service account role %s/%s for %s: %w", objectMeta.Name, objectMeta.Namespace, gvk.Kind, err) + } + + return nil + } + + if err != nil { + return fmt.Errorf("could not get OIDC service account role %s/%s for %s: %w", objectMeta.Name, objectMeta.Namespace, gvk.Kind, err) + + } + return nil +} diff --git a/pkg/reconciler/apiserversource/resources/role_binding.go b/pkg/reconciler/apiserversource/resources/role_binding.go new file mode 100644 index 00000000000..032d6b53a57 --- /dev/null +++ b/pkg/reconciler/apiserversource/resources/role_binding.go @@ -0,0 +1,46 @@ +/* +Copyright 2020 The Knative Authors + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package resources + +import ( + corev1 "k8s.io/api/core/v1" + rbacv1 "k8s.io/api/rbac/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" +) + +// MakeRoleBinding creates a RoleBinding object for the Apiserversource +// service account 'sa' in the Namespace 'ns'. +func MakeRoleBinding(ns, name string, sa *corev1.ServiceAccount, roleName string) *rbacv1.RoleBinding { + return &rbacv1.RoleBinding{ + ObjectMeta: metav1.ObjectMeta{ + Name: name, + Namespace: ns, + }, + RoleRef: rbacv1.RoleRef{ + APIGroup: "rbac.authorization.k8s.io", + Kind: "ClusterRole", + Name: roleName, + }, + Subjects: []rbacv1.Subject{ + { + Kind: "ServiceAccount", + Namespace: sa.Namespace, + Name: sa.Name, + }, + }, + } +} diff --git a/pkg/reconciler/inmemorychannel/controller/resources/role_binding.go b/pkg/reconciler/inmemorychannel/controller/resources/role_binding.go index 4c835878174..21ce06407bc 100644 --- a/pkg/reconciler/inmemorychannel/controller/resources/role_binding.go +++ b/pkg/reconciler/inmemorychannel/controller/resources/role_binding.go @@ -32,7 +32,7 @@ func MakeRoleBinding(ns, name string, sa *corev1.ServiceAccount, roleName string }, RoleRef: rbacv1.RoleRef{ APIGroup: "rbac.authorization.k8s.io", - Kind: "ClusterRole", + Kind: "Role", Name: roleName, }, Subjects: []rbacv1.Subject{ From 8b4463ca38f390195304cfafd27fdabac684c7ad Mon Sep 17 00:00:00 2001 From: Leo Li Date: Fri, 24 Nov 2023 08:38:55 -0500 Subject: [PATCH 06/62] Adding the rolebinding for create_oidc Signed-off-by: Leo Li --- .../apiserversource/apiserversource.go | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/pkg/reconciler/apiserversource/apiserversource.go b/pkg/reconciler/apiserversource/apiserversource.go index 0ed020ec864..0aa2d6b4489 100644 --- a/pkg/reconciler/apiserversource/apiserversource.go +++ b/pkg/reconciler/apiserversource/apiserversource.go @@ -106,11 +106,20 @@ func (r *Reconciler) ReconcileKind(ctx context.Context, source *v1.ApiServerSour ServiceAccountName: &saName, } + // set the role for the service account + if err := auth.EnsureOIDCServiceAccountExistsForResource(ctx, r.serviceAccountLister, r.kubeClientSet, v1.SchemeGroupVersion.WithKind("ApiServerSource"), source.ObjectMeta); err != nil { source.Status.MarkOIDCIdentityCreatedFailed("Unable to resolve service account for OIDC authentication", "%v", err) return err } source.Status.MarkOIDCIdentityCreatedSucceeded() + + // TODO: add the role binding + if err := auth.EnsureOIDCServiceAccountRoleBindingExistsForResource(ctx, r.kubeClientSet, v1.SchemeGroupVersion.WithKind("ApiServerSource"), source.ObjectMeta); err != nil { + source.Status.MarkOIDCIdentityCreatedFailed("Unable to resolve role binding for OIDC authentication", "%v", err) + return err + } + } else { source.Status.Auth = nil source.Status.MarkOIDCIdentityCreatedSucceededWithReason(fmt.Sprintf("%s feature disabled", feature.OIDCAuthentication), "") @@ -204,6 +213,11 @@ func (r *Reconciler) createReceiveAdapter(ctx context.Context, src *v1.ApiServer // return nil, err // } + fmt.Printf("haha sinkAddr: %v\n", sinkAddr) + fmt.Printf("haha sinkAddr.URL: %v\n", sinkAddr.URL) + fmt.Printf("haha sinkAddr.URL.String(): %v\n", sinkAddr.URL.String()) + fmt.Printf("haha sinkAddr.audience: %v\n", sinkAddr.Audience) + adapterArgs := resources.ReceiveAdapterArgs{ Image: r.receiveAdapterImage, Source: src, @@ -349,3 +363,5 @@ func (r *Reconciler) createCloudEventAttributes(src *v1.ApiServerSource) ([]duck } return ceAttributes, nil } + +// TODO: adding the rolebinding function to the resource folder and the role to the auth folder From ef855c84d6117110430d6ac9c2817e22ddb35b0f Mon Sep 17 00:00:00 2001 From: Leo Li Date: Fri, 24 Nov 2023 09:08:04 -0500 Subject: [PATCH 07/62] Update the env variable Signed-off-by: Leo Li --- .../resources/receive_adapter.go | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) diff --git a/pkg/reconciler/apiserversource/resources/receive_adapter.go b/pkg/reconciler/apiserversource/resources/receive_adapter.go index 33ef12106d9..2c48292cad5 100644 --- a/pkg/reconciler/apiserversource/resources/receive_adapter.go +++ b/pkg/reconciler/apiserversource/resources/receive_adapter.go @@ -19,7 +19,6 @@ package resources import ( "encoding/json" "fmt" - "knative.dev/eventing/pkg/adapter/v2" appsv1 "k8s.io/api/apps/v1" @@ -121,6 +120,7 @@ func MakeReceiveAdapter(args *ReceiveAdapterArgs) (*appsv1.Deployment, error) { } func makeEnv(args *ReceiveAdapterArgs) ([]corev1.EnvVar, error) { + fmt.Printf("haha geting started make Env") cfg := &apiserver.Config{ Namespaces: args.Namespaces, Resources: make([]apiserver.ResourceWatch, 0, len(args.Source.Spec.Resources)), @@ -154,9 +154,6 @@ func makeEnv(args *ReceiveAdapterArgs) ([]corev1.EnvVar, error) { envs := []corev1.EnvVar{{ Name: adapter.EnvConfigSink, Value: args.SinkURI, - }, { - Name: "K_AUDIENCE", - Value: *args.Audience, }, { Name: "K_SOURCE_CONFIG", Value: config, @@ -185,6 +182,20 @@ func makeEnv(args *ReceiveAdapterArgs) ([]corev1.EnvVar, error) { }) } + fmt.Printf("haha receive_adapter: trying to add the k_audience env var\n") + if args.Audience != nil { + fmt.Printf("haha receive_adapter: adding the k_audience env var\n") + envs = append(envs, corev1.EnvVar{ + Name: "K_AUDIENCE", + Value: *args.Audience, + }) + } else { + envs = append(envs, corev1.EnvVar{ + Name: "K_AUDIENCE", + Value: "0000", + }) + } + envs = append(envs, args.Configs.ToEnvVars()...) if args.Source.Spec.CloudEventOverrides != nil { From 5c134b3637c54c6cf8f441d7d330b2912a83bcc2 Mon Sep 17 00:00:00 2001 From: Leo Li Date: Fri, 24 Nov 2023 11:19:26 -0500 Subject: [PATCH 08/62] Revert the automated change to the file Signed-off-by: Leo Li --- .../inmemorychannel/controller/resources/role_binding.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkg/reconciler/inmemorychannel/controller/resources/role_binding.go b/pkg/reconciler/inmemorychannel/controller/resources/role_binding.go index 21ce06407bc..4c835878174 100644 --- a/pkg/reconciler/inmemorychannel/controller/resources/role_binding.go +++ b/pkg/reconciler/inmemorychannel/controller/resources/role_binding.go @@ -32,7 +32,7 @@ func MakeRoleBinding(ns, name string, sa *corev1.ServiceAccount, roleName string }, RoleRef: rbacv1.RoleRef{ APIGroup: "rbac.authorization.k8s.io", - Kind: "Role", + Kind: "ClusterRole", Name: roleName, }, Subjects: []rbacv1.Subject{ From 4d3caecb9eb2a701a53021918ad179780ddb28b1 Mon Sep 17 00:00:00 2001 From: Leo Li Date: Fri, 24 Nov 2023 11:20:45 -0500 Subject: [PATCH 09/62] Update pkg/adapter/apiserver/delegate.go MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Christoph Stäbler --- pkg/adapter/apiserver/delegate.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkg/adapter/apiserver/delegate.go b/pkg/adapter/apiserver/delegate.go index f1f595e529e..075f095d974 100644 --- a/pkg/adapter/apiserver/delegate.go +++ b/pkg/adapter/apiserver/delegate.go @@ -79,7 +79,7 @@ func (a *resourceDelegate) sendCloudEvent(ctx context.Context, event cloudevents // ?? Question: where can we get the sink audience? As we don't specify the destination in the cloudevent // If the sink has audience, then we need to request the JWT token - // In order to request the JWT token, we need to get the service account name and namespace from the sink + // In order to request the JWT token, we need to get the service account name and namespace from the source // And also need to pass in OIDC token provider // ?? Question again: where can we get the sink audience? And how to pass in OIDC token provider? From 0cab4e5a1fbb94d9e27fcaaa040a9ca33267adfd Mon Sep 17 00:00:00 2001 From: Leo Li Date: Fri, 24 Nov 2023 11:21:07 -0500 Subject: [PATCH 10/62] Apply suggestions from code review Co-authored-by: Calum Murray --- pkg/adapter/apiserver/delegate.go | 1 + pkg/adapter/v2/cloudevents.go | 1 + 2 files changed, 2 insertions(+) diff --git a/pkg/adapter/apiserver/delegate.go b/pkg/adapter/apiserver/delegate.go index 075f095d974..21cb343e43f 100644 --- a/pkg/adapter/apiserver/delegate.go +++ b/pkg/adapter/apiserver/delegate.go @@ -18,6 +18,7 @@ package apiserver import ( "context" + cloudevents "github.com/cloudevents/sdk-go/v2" "github.com/google/uuid" "go.uber.org/zap" diff --git a/pkg/adapter/v2/cloudevents.go b/pkg/adapter/v2/cloudevents.go index 2e43c1708d8..646a50a855e 100644 --- a/pkg/adapter/v2/cloudevents.go +++ b/pkg/adapter/v2/cloudevents.go @@ -20,6 +20,7 @@ import ( "context" "errors" "fmt" + "k8s.io/apimachinery/pkg/types" "knative.dev/eventing/pkg/auth" nethttp "net/http" From 7190e7ef03f4cbfba0d37882574ddf7a2488f528 Mon Sep 17 00:00:00 2001 From: Leo Li Date: Mon, 4 Dec 2023 00:27:03 -0500 Subject: [PATCH 11/62] Save the working progress - 2 Signed-off-by: Leo Li --- .../core/roles/controller-clusterroles.yaml | 2 + pkg/adapter/apiserver/delegate.go | 6 +- pkg/adapter/v2/cloudevents.go | 56 +++++-- pkg/adapter/v2/config.go | 41 ++++- pkg/adapter/v2/main.go | 3 +- pkg/auth/serviceaccount.go | 147 +++++++++++++++++- pkg/auth/token_provider.go | 2 + .../apiserversource/apiserversource.go | 27 +++- .../resources/receive_adapter.go | 22 +-- test/auth/features/oidc/apiserversource.go | 26 ++-- test/auth/oidc_test.go | 2 - .../apiserversource/apiserversource.go | 4 + 12 files changed, 283 insertions(+), 55 deletions(-) diff --git a/config/core/roles/controller-clusterroles.yaml b/config/core/roles/controller-clusterroles.yaml index b123b2bf0d0..b76d16ebd3e 100644 --- a/config/core/roles/controller-clusterroles.yaml +++ b/config/core/roles/controller-clusterroles.yaml @@ -31,6 +31,7 @@ rules: - "events" - "serviceaccounts" - "pods" + - "serviceaccounts/token" verbs: &everything - "get" - "list" @@ -60,6 +61,7 @@ rules: - "rbac.authorization.k8s.io" resources: - "rolebindings" + - "roles" verbs: *everything # Our own resources and statuses we care about. diff --git a/pkg/adapter/apiserver/delegate.go b/pkg/adapter/apiserver/delegate.go index 21cb343e43f..d88569dc020 100644 --- a/pkg/adapter/apiserver/delegate.go +++ b/pkg/adapter/apiserver/delegate.go @@ -18,7 +18,7 @@ package apiserver import ( "context" - + cloudevents "github.com/cloudevents/sdk-go/v2" "github.com/google/uuid" "go.uber.org/zap" @@ -73,7 +73,7 @@ func (a *resourceDelegate) sendCloudEvent(ctx context.Context, event cloudevents defer a.logger.Debug("Finished sending cloudevent id: ", event.ID()) source := event.Context.GetSource() subject := event.Context.GetSubject() - a.logger.Debugf("sending cloudevent id: %s, source: %s, subject: %s", event.ID(), source, subject) + a.logger.Info("sending cloudevent id: %s, source: %s, subject: %s", event.ID(), source, subject) // Decide whether to request the JWT token or not // Condition: if the sink has audience or not @@ -105,7 +105,7 @@ func (a *resourceDelegate) sendCloudEvent(ctx context.Context, event cloudevents a.logger.Errorw("failed to send cloudevent", zap.Error(result), zap.String("source", source), zap.String("subject", subject), zap.String("id", event.ID())) } else { - a.logger.Debugf("cloudevent sent id: %s, source: %s, subject: %s", event.ID(), source, subject) + a.logger.Info("cloudevent sent id: %s, source: %s, subject: %s", event.ID(), source, subject) } } diff --git a/pkg/adapter/v2/cloudevents.go b/pkg/adapter/v2/cloudevents.go index 646a50a855e..2a662815891 100644 --- a/pkg/adapter/v2/cloudevents.go +++ b/pkg/adapter/v2/cloudevents.go @@ -23,6 +23,7 @@ import ( "k8s.io/apimachinery/pkg/types" "knative.dev/eventing/pkg/auth" + "knative.dev/pkg/logging" nethttp "net/http" "net/url" "time" @@ -108,12 +109,12 @@ func NewCloudEventsClientCRStatus(env EnvConfigAccessor, reporter source.StatsRe } type ClientConfig struct { - Context context.Context Env EnvConfigAccessor CeOverrides *duckv1.CloudEventOverrides Reporter source.StatsReporter CrStatusEventClient *crstatusevent.CRStatusEventClient Options []http.Option + TokenProvider *auth.OIDCTokenProvider } type clientConfigKey struct{} @@ -138,6 +139,8 @@ func NewClient(cfg ClientConfig) (Client, error) { pOpts := make([]http.Option, 0) + //OIDCTokenProvider := auth.NewOIDCTokenProvider(cfg.Context) + ceOverrides := cfg.CeOverrides if cfg.Env != nil { if target := cfg.Env.GetSink(); len(target) > 0 { @@ -146,6 +149,7 @@ func NewClient(cfg ClientConfig) (Client, error) { if sinkWait := cfg.Env.GetSinktimeout(); sinkWait > 0 { pOpts = append(pOpts, setTimeOut(time.Duration(sinkWait)*time.Second)) } + if eventingtls.IsHttpsSink(cfg.Env.GetSink()) { var err error @@ -165,6 +169,7 @@ func NewClient(cfg ClientConfig) (Client, error) { Propagation: tracecontextb3.TraceContextEgress, } } + if ceOverrides == nil { var err error ceOverrides, err = cfg.Env.GetCloudEventOverrides() @@ -193,14 +198,16 @@ func NewClient(cfg ClientConfig) (Client, error) { if err != nil { return nil, err } + return &client{ ceClient: ceClient, closeIdler: transport.Base.(*nethttp.Transport), ceOverrides: ceOverrides, reporter: cfg.Reporter, crStatusEventClient: cfg.CrStatusEventClient, - oidcTokenProvider: auth.NewOIDCTokenProvider(cfg.Context), audience: cfg.Env.GetAudience(), + serviceAccountName: cfg.Env.GetServiceAccountName(), + oidcTokenProvider: cfg.TokenProvider, }, nil } @@ -225,7 +232,7 @@ type client struct { closeIdler closeIdler oidcTokenProvider *auth.OIDCTokenProvider - audience *string + audience string serviceAccountName types.NamespacedName } @@ -239,10 +246,23 @@ var _ cloudevents.Client = (*client)(nil) func (c *client) Send(ctx context.Context, out event.Event) protocol.Result { c.applyOverrides(&out) + logger := logging.FromContext(ctx) + logger.Errorf("haha send: trying to execute Send function") + + logger.Errorf("haha send: print service account name: %s", c.serviceAccountName.Name) + logger.Errorf("haha send: print service account namespace: %s", c.serviceAccountName.Namespace) + //logger.Errorf("haha send: print audience: %s", c.audience) + //logger.Errorf("haha send: print the audience, and audience is a string pointer: %s", *c.audience) + logger.Errorf("haha send: conclude, now going to generate the jwt token") + // If the sink has audience, then we need to request the JWT token - if c.audience != nil { + if c.audience != "" { // Request the JWT token for the given service account - jwt, err := c.oidcTokenProvider.GetJWT(c.serviceAccountName, *c.audience) + //jwt, err := c.oidcTokenProvider.GetJWT(c.serviceAccountName, *c.audience) + jwt, err := c.oidcTokenProvider.GetJWT(c.serviceAccountName, c.audience) + + logger.Errorf("haha send: print jwt: %s", jwt) + logger.Errorf("haha send: print err: %s", err) if err != nil { return protocol.NewResult("%w", err) @@ -250,7 +270,7 @@ func (c *client) Send(ctx context.Context, out event.Event) protocol.Result { // Appending the auth token to the outgoing request headers := http.HeaderFrom(ctx) - headers.Set("Authentication", fmt.Sprintf("Bearer %s", jwt)) + headers.Set("Authorization", fmt.Sprintf("Bearer %s", jwt)) ctx = http.WithCustomHeader(ctx, headers) } @@ -264,19 +284,21 @@ func (c *client) Request(ctx context.Context, out event.Event) (*event.Event, pr c.applyOverrides(&out) // If the sink has audience, then we need to request the JWT token - if c.audience != nil { - // Request the JWT token for the given service account - jwt, err := c.oidcTokenProvider.GetJWT(c.serviceAccountName, *c.audience) + logger := logging.FromContext(ctx) + logger.Errorf("haha send: trying to execute Send function") - if err != nil { - return nil, protocol.NewResult("%w", err) - } + logger.Errorf("haha req: print service account name: %s", c.serviceAccountName.Name) + logger.Errorf("haha req: print service account namespace: %s", c.serviceAccountName.Namespace) + //logger.Errorf("haha req: print audience: %s", c.audience) + logger.Errorf("haha req: conclude, now going to generate the jwt token") - // Appending the auth token to the outgoing request - headers := http.HeaderFrom(ctx) - headers.Set("Authentication", fmt.Sprintf("Bearer %s", jwt)) - ctx = http.WithCustomHeader(ctx, headers) - } + // If the sink has audience, then we need to request the JWT token + //if c.audience != nil{ + // Request the JWT token for the given service account + jwt, err := c.oidcTokenProvider.GetJWT(c.serviceAccountName, "my-sink-audience") + + logger.Errorf("haha send: print jwt: %s", jwt) + logger.Errorf("haha send: print err: %s", err) resp, res := c.ceClient.Request(ctx, out) c.reportMetrics(ctx, out, res) diff --git a/pkg/adapter/v2/config.go b/pkg/adapter/v2/config.go index 6386b38e6ea..9bde95e237e 100644 --- a/pkg/adapter/v2/config.go +++ b/pkg/adapter/v2/config.go @@ -17,8 +17,11 @@ package adapter import ( "encoding/json" + "fmt" + "k8s.io/apimachinery/pkg/types" "os" "strconv" + "strings" "time" "go.uber.org/zap" @@ -39,6 +42,7 @@ const ( EnvConfigName = "NAME" EnvConfigResourceGroup = "K_RESOURCE_GROUP" EnvConfigSink = "K_SINK" + EnvConfigAudience = "K_AUDIENCE" EnvConfigCACert = "K_CA_CERTS" EnvConfigCEOverrides = "K_CE_OVERRIDES" EnvConfigMetricsConfig = "K_METRICS_CONFIG" @@ -67,7 +71,10 @@ type EnvConfig struct { Sink string `envconfig:"K_SINK"` // Audience is the audience of the target sink. - Audience *string `envconfig:"K_AUDIENCE"` + Audience string `envconfig:"K_AUDIENCE"` + + // Service Account Name is the name of the service account to use for the adapter. + ServiceAccountName *string `envconfig:"K_OIDC_SERVICE_ACCOUNT"` // CACerts are the Certification Authority (CA) certificates in PEM format // according to https://www.rfc-editor.org/rfc/rfc7468. @@ -117,7 +124,9 @@ type EnvConfigAccessor interface { GetCACerts() *string // Get the audience of the target sink. - GetAudience() *string + GetAudience() string + + GetServiceAccountName() types.NamespacedName // Get the namespace of the adapter. GetNamespace() string @@ -157,6 +166,24 @@ func (e *EnvConfig) GetMetricsConfig() (*metrics.ExporterOptions, error) { return metricsConfig, err } +func extractSinkName(url string) (string, error) { + // Check if URL contains http://, remove it for easier processing + if strings.HasPrefix(url, "http://") { + url = strings.TrimPrefix(url, "http://") + } + + // Split the URL by '.' to isolate the components + parts := strings.Split(url, ".") + if len(parts) == 0 { + return "", fmt.Errorf("invalid URL format") + } + + // The first part of the URL is expected to be the sink name + sinkName := parts[0] + + return sinkName, nil +} + func (e *EnvConfig) GetLogger() *zap.SugaredLogger { if e.logger == nil { loggingConfig, err := logging.JSONToConfig(e.LoggingConfigJson) @@ -178,11 +205,19 @@ func (e *EnvConfig) GetSink() string { return e.Sink } +func (e *EnvConfig) GetServiceAccountName() types.NamespacedName { + + return types.NamespacedName{ + Namespace: e.Namespace, + Name: *e.ServiceAccountName, + } +} + func (e *EnvConfig) GetCACerts() *string { return e.CACerts } -func (e *EnvConfig) GetAudience() *string { +func (e *EnvConfig) GetAudience() string { return e.Audience } diff --git a/pkg/adapter/v2/main.go b/pkg/adapter/v2/main.go index 217482151c4..70b12719250 100644 --- a/pkg/adapter/v2/main.go +++ b/pkg/adapter/v2/main.go @@ -20,6 +20,7 @@ import ( "context" "flag" "fmt" + "knative.dev/eventing/pkg/auth" "log" "net/http" "strconv" @@ -215,10 +216,10 @@ func MainWithInformers(ctx context.Context, component string, env EnvConfigAcces } clientConfig := ClientConfig{ - Context: ctx, Env: env, Reporter: reporter, CrStatusEventClient: crStatusEventClient, + TokenProvider: auth.NewOIDCTokenProvider(ctx), } ctx = withClientConfig(ctx, clientConfig) diff --git a/pkg/auth/serviceaccount.go b/pkg/auth/serviceaccount.go index 01e31f4b642..e09bb2a428a 100644 --- a/pkg/auth/serviceaccount.go +++ b/pkg/auth/serviceaccount.go @@ -19,6 +19,10 @@ package auth import ( "context" "fmt" + rbacv1 "k8s.io/api/rbac/v1" + "knative.dev/eventing/pkg/apis/feature" + duckv1 "knative.dev/pkg/apis/duck/v1" + pkgreconciler "knative.dev/pkg/reconciler" "strings" "go.uber.org/zap" @@ -28,11 +32,8 @@ import ( "k8s.io/apimachinery/pkg/runtime/schema" "k8s.io/client-go/kubernetes" corev1listers "k8s.io/client-go/listers/core/v1" - "knative.dev/eventing/pkg/apis/feature" - duckv1 "knative.dev/pkg/apis/duck/v1" "knative.dev/pkg/logging" "knative.dev/pkg/ptr" - pkgreconciler "knative.dev/pkg/reconciler" ) // GetOIDCServiceAccountNameForResource returns the service account name to use @@ -121,3 +122,143 @@ func SetupOIDCServiceAccount(ctx context.Context, flags feature.Flags, serviceAc } return nil } + +// EnsureOIDCServiceAccountRoleBindingExistsForResource +// makes sure the given resource has an OIDC service account role binding with +// an owner reference to the resource set. +func EnsureOIDCServiceAccountRoleBindingExistsForResource(ctx context.Context, kubeclient kubernetes.Interface, gvk schema.GroupVersionKind, objectMeta metav1.ObjectMeta, saName string) error { + logger := logging.FromContext(ctx) + logger.Errorf("haha: Initializing") + + roleName := fmt.Sprintf("create-oidc-token") + roleBindingName := fmt.Sprintf("create-oidc-token") + + logger.Errorf("haha: going to get role binding for %s", objectMeta.Name) + logger.Errorf("haha: role name %s", roleName) + logger.Errorf("haha: role binding name %s", roleBindingName) + + roleBinding, err := kubeclient.RbacV1().RoleBindings(objectMeta.Namespace).Get(ctx, roleBindingName, metav1.GetOptions{}) + + logger.Errorf("haha: got role binding for %s", roleBinding) + + logger.Errorf("haha: going to enter the if statement") + // If the resource doesn't exist, we'll create it. + if apierrs.IsNotFound(err) { + logging.FromContext(ctx).Debugw("Creating OIDC service account role binding", zap.Error(err)) + logger.Errorf("haha: creating role binding") + + // Create the "create-oidc-token" role + CreateRoleForServiceAccount(ctx, kubeclient, gvk, objectMeta) + + roleBinding = &rbacv1.RoleBinding{ + ObjectMeta: metav1.ObjectMeta{ + Name: roleBindingName, + Namespace: objectMeta.GetNamespace(), + Annotations: map[string]string{ + "description": fmt.Sprintf("Role Binding for OIDC Authentication for %s %q", gvk.GroupKind().Kind, objectMeta.Name), + }, + }, + RoleRef: rbacv1.RoleRef{ + APIGroup: "rbac.authorization.k8s.io", + Kind: "Role", + //objectMeta.Name + roleName + Name: fmt.Sprintf(roleName), + }, + Subjects: []rbacv1.Subject{ + { + Kind: "ServiceAccount", + Namespace: objectMeta.GetNamespace(), + // apiServerSource service account name, it is in the source.Spec, NOT in source.Auth + Name: saName, + }, + }, + } + + logger.Errorf("haha: role binding object created") + logger.Errorf("haha: role binding object %s", roleBinding) + + _, err = kubeclient.RbacV1().RoleBindings(objectMeta.Namespace).Create(ctx, roleBinding, metav1.CreateOptions{}) + if err != nil { + logger.Errorf("haha: error creating role binding") + logger.Errorf("haha: error %s", err) + return fmt.Errorf("could not create OIDC service account role binding %s/%s for %s: %w", objectMeta.Name, objectMeta.Namespace, gvk.Kind, err) + } + + return nil + } + + if err != nil { + logger.Errorf("haha: error getting role binding") + logger.Errorf("haha: error %s", err) + return fmt.Errorf("could not get OIDC service account role binding %s/%s for %s: %w", objectMeta.Name, objectMeta.Namespace, gvk.Kind, err) + + } + + if !metav1.IsControlledBy(&roleBinding.ObjectMeta, &objectMeta) { + logger.Errorf("haha: role binding not owned by") + logger.Errorf("haha: role binding %s", roleBinding) + return fmt.Errorf("role binding %s not owned by %s %s", roleBinding.Name, gvk.Kind, objectMeta.Name) + } + + return nil +} + +// Create the create-oidc-token role for the service account +func CreateRoleForServiceAccount(ctx context.Context, kubeclient kubernetes.Interface, gvk schema.GroupVersionKind, objectMeta metav1.ObjectMeta) error { + + logger := logging.FromContext(ctx) + logger.Errorf("haha: Initializing create role for service account") + + roleName := fmt.Sprintf("create-oidc-token") + logger.Errorf("haha: role name %s", roleName) + + role, err := kubeclient.RbacV1().Roles(objectMeta.Namespace).Get(ctx, roleName, metav1.GetOptions{}) + logger.Errorf("haha: got role %s", role) + + // If the resource doesn't exist, we'll create it. + if apierrs.IsNotFound(err) { + logging.FromContext(ctx).Debugw("Creating OIDC service account role", zap.Error(err)) + + logger.Errorf("haha: creating role") + + role = &rbacv1.Role{ + ObjectMeta: metav1.ObjectMeta{ + Name: roleName, + Namespace: objectMeta.GetNamespace(), + Annotations: map[string]string{ + "description": fmt.Sprintf("Role for OIDC Authentication for %s %q", gvk.GroupKind().Kind, objectMeta.Name), + }, + }, + Rules: []rbacv1.PolicyRule{ + rbacv1.PolicyRule{ + APIGroups: []string{""}, + + // serviceaccount name + ResourceNames: []string{GetOIDCServiceAccountNameForResource(gvk, objectMeta)}, + Resources: []string{"serviceaccounts/token"}, + Verbs: []string{"create"}, + }, + }, + } + + logger.Errorf("haha: role object created") + logger.Errorf("haha: role object %s", role) + + _, err = kubeclient.RbacV1().Roles(objectMeta.Namespace).Create(ctx, role, metav1.CreateOptions{}) + if err != nil { + logger.Errorf("haha: error creating role") + logger.Errorf("haha: error %s", err) + return fmt.Errorf("could not create OIDC service account role %s/%s for %s: %w", objectMeta.Name, objectMeta.Namespace, gvk.Kind, err) + } + + return nil + } + + if err != nil { + logger.Errorf("haha: error getting role") + logger.Errorf("haha: error getting role %s", err) + return fmt.Errorf("could not get OIDC service account role %s/%s for %s: %w", objectMeta.Name, objectMeta.Namespace, gvk.Kind, err) + + } + return nil +} diff --git a/pkg/auth/token_provider.go b/pkg/auth/token_provider.go index 6fb115f9d4e..2d5423ecc41 100644 --- a/pkg/auth/token_provider.go +++ b/pkg/auth/token_provider.go @@ -79,6 +79,8 @@ func (c *OIDCTokenProvider) GetNewJWT(serviceAccount types.NamespacedName, audie CreateToken(context.TODO(), serviceAccount.Name, &tokenRequest, metav1.CreateOptions{}) if err != nil { + fmt.Sprintf("could not request a token for %s: %w", serviceAccount, err) + return "", fmt.Errorf("could not request a token for %s: %w", serviceAccount, err) } diff --git a/pkg/reconciler/apiserversource/apiserversource.go b/pkg/reconciler/apiserversource/apiserversource.go index 6cfd976751c..b7b4a53a300 100644 --- a/pkg/reconciler/apiserversource/apiserversource.go +++ b/pkg/reconciler/apiserversource/apiserversource.go @@ -106,6 +106,11 @@ func (r *Reconciler) ReconcileKind(ctx context.Context, source *v1.ApiServerSour return err } + // Create the role and rolebinding + logging.FromContext(ctx).Errorw("haha: About to enter the role access granting stage Creating role and rolebinding") + auth.EnsureOIDCServiceAccountRoleBindingExistsForResource(ctx, r.kubeClientSet, v1.SchemeGroupVersion.WithKind("ApiServerSource"), source.ObjectMeta, source.Spec.ServiceAccountName) + + logging.FromContext(ctx).Errorw("haha: finished About to enter the role access granting stage Creating role and rolebinding") sinkAddr, err := r.sinkResolver.AddressableFromDestinationV1(ctx, *dest, source) if err != nil { source.Status.MarkNoSink("NotFound", "") @@ -113,6 +118,10 @@ func (r *Reconciler) ReconcileKind(ctx context.Context, source *v1.ApiServerSour } source.Status.MarkSink(sinkAddr) + // The audience should already be specified + logging.FromContext(ctx).Errorw("haha: try to display source sink ref", zap.Any("audience is", source.Spec.Sink.Audience)) + logging.FromContext(ctx).Errorw("haha try to display sinkAddr Audience", zap.Any("audience is", sinkAddr.Audience)) + // resolve namespaces to watch namespaces, err := r.namespacesFromSelector(source) if err != nil { @@ -134,8 +143,12 @@ func (r *Reconciler) ReconcileKind(ctx context.Context, source *v1.ApiServerSour logging.FromContext(ctx).Errorw("Unable to create the receive adapter", zap.Error(err)) return err } + + logging.FromContext(ctx).Debugw("haha: Receive adapter created", zap.Any("receiveAdapter", ra)) source.Status.PropagateDeploymentAvailability(ra) + logging.FromContext(ctx).Debugw("haha: Creating CloudEventAttributes") + cloudEventAttributes, err := r.createCloudEventAttributes(source) if err != nil { logging.FromContext(ctx).Errorw("Unable to create CloudEventAttributes", zap.Error(err)) @@ -199,13 +212,22 @@ func (r *Reconciler) createReceiveAdapter(ctx context.Context, src *v1.ApiServer fmt.Printf("haha sinkAddr.URL.String(): %v\n", sinkAddr.URL.String()) fmt.Printf("haha sinkAddr.audience: %v\n", sinkAddr.Audience) + var audience string + if sinkAddr.Audience != nil { + audience = *sinkAddr.Audience + } else { + audience = "ilovehaha" + } + + // trying to figure out why audience is empty + adapterArgs := resources.ReceiveAdapterArgs{ Image: r.receiveAdapterImage, Source: src, Labels: resources.Labels(src.Name), CACerts: sinkAddr.CACerts, SinkURI: sinkAddr.URL.String(), - Audience: sinkAddr.Audience, + Audience: audience, Configs: r.configs, Namespaces: namespaces, AllNamespaces: allNamespaces, @@ -262,10 +284,13 @@ func (r *Reconciler) runAccessCheck(ctx context.Context, src *v1.ApiServerSource return nil } + // Run the basic service account access check (This is not OIDC service account) user := "system:serviceaccount:" + src.Namespace + ":" if src.Spec.ServiceAccountName == "" { + logging.FromContext(ctx).Debugw("haha No ServiceAccountName specified, using default") user += "default" } else { + logging.FromContext(ctx).Debugw("haha Using ServiceAccountName", zap.String("ServiceAccountName", src.Spec.ServiceAccountName)) user += src.Spec.ServiceAccountName } diff --git a/pkg/reconciler/apiserversource/resources/receive_adapter.go b/pkg/reconciler/apiserversource/resources/receive_adapter.go index 2c48292cad5..416f26230c5 100644 --- a/pkg/reconciler/apiserversource/resources/receive_adapter.go +++ b/pkg/reconciler/apiserversource/resources/receive_adapter.go @@ -19,14 +19,13 @@ package resources import ( "encoding/json" "fmt" - "knative.dev/eventing/pkg/adapter/v2" - appsv1 "k8s.io/api/apps/v1" corev1 "k8s.io/api/core/v1" "k8s.io/apimachinery/pkg/api/meta" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime/schema" "k8s.io/apimachinery/pkg/util/intstr" + "knative.dev/eventing/pkg/adapter/v2" "knative.dev/pkg/kmeta" "knative.dev/pkg/ptr" @@ -43,7 +42,7 @@ type ReceiveAdapterArgs struct { Image string Source *v1.ApiServerSource Labels map[string]string - Audience *string + Audience string SinkURI string CACerts *string Configs reconcilersource.ConfigAccessor @@ -173,7 +172,12 @@ func makeEnv(args *ReceiveAdapterArgs) ([]corev1.EnvVar, error) { }, { Name: "METRICS_DOMAIN", Value: "knative.dev/eventing", - }} + }, + { + Name: "K_OIDC_SERVICE_ACCOUNT", + Value: *args.Source.Status.Auth.ServiceAccountName, + }, + } if args.CACerts != nil { envs = append(envs, corev1.EnvVar{ @@ -183,16 +187,12 @@ func makeEnv(args *ReceiveAdapterArgs) ([]corev1.EnvVar, error) { } fmt.Printf("haha receive_adapter: trying to add the k_audience env var\n") - if args.Audience != nil { + fmt.Printf("haha receive_adapter: args.Audience is %v\n", args.Audience) + if args.Audience != "" { fmt.Printf("haha receive_adapter: adding the k_audience env var\n") envs = append(envs, corev1.EnvVar{ Name: "K_AUDIENCE", - Value: *args.Audience, - }) - } else { - envs = append(envs, corev1.EnvVar{ - Name: "K_AUDIENCE", - Value: "0000", + Value: args.Audience, }) } diff --git a/test/auth/features/oidc/apiserversource.go b/test/auth/features/oidc/apiserversource.go index 99bc5dcdf0f..20e564d2e49 100644 --- a/test/auth/features/oidc/apiserversource.go +++ b/test/auth/features/oidc/apiserversource.go @@ -21,8 +21,6 @@ import ( "github.com/cloudevents/sdk-go/v2/test" rbacv1 "k8s.io/api/rbac/v1" v1 "knative.dev/eventing/pkg/apis/sources/v1" - "knative.dev/eventing/test/rekt/features/featureflags" - "knative.dev/eventing/test/rekt/features/source" "knative.dev/eventing/test/rekt/resources/account_role" "knative.dev/eventing/test/rekt/resources/apiserversource" "knative.dev/reconciler-test/pkg/eventshub" @@ -43,17 +41,17 @@ func ApiserversourceSendEventWithJWT() *feature.Feature { audience := "my-sink-audience" sacmName := feature.MakeRandomK8sName("apiserversource") - f := feature.NewFeatureNamed("Send events to TLS sink") + f := feature.NewFeatureNamed("Send events to sink") - f.Prerequisite("should not run when Istio is enabled", featureflags.IstioDisabled()) - f.Prerequisite("transport encryption is strict", featureflags.TransportEncryptionStrict()) + //f.Prerequisite("should not run when Istio is enabled", featureflags.IstioDisabled()) + //f.Prerequisite("transport encryption is strict", featureflags.TransportEncryptionStrict()) f.Setup("deploy receiver", eventshub.Install(sink, eventshub.StartReceiver, eventshub.OIDCReceiverAudience(audience))) - + // f.Setup("Create Service Account for ApiServerSource with RBAC for v1.Event resources", - setupAccountAndRoleForPods(sacmName)) + setupAccountAndRoleForApiserversource(sacmName)) cfg := []manifest.CfgFn{ apiserversource.WithServiceAccountName(sacmName), @@ -66,7 +64,7 @@ func ApiserversourceSendEventWithJWT() *feature.Feature { f.Requirement("install ApiServerSource", func(ctx context.Context, t feature.T) { d := service.AsDestinationRef(sink) - d.CACerts = eventshub.GetCaCerts(ctx) + d.Audience = &audience cfg = append(cfg, apiserversource.WithSink(d)) apiserversource.Install(src, cfg...)(ctx, t) @@ -85,20 +83,20 @@ func ApiserversourceSendEventWithJWT() *feature.Feature { Match(eventasssert.MatchKind(eventshub.EventReceived)). MatchEvent(test.HasType("dev.knative.apiserver.resource.update")). AtLeast(1), - ). - Must("Set sinkURI to HTTPS endpoint", source.ExpectHTTPSSink(apiserversource.Gvr(), src)). - Must("Set sinkCACerts to non empty CA certs", source.ExpectCACerts(apiserversource.Gvr(), src)) + ) + //Must("Set sinkURI to HTTPS endpoint", source.ExpectHTTPSSink(apiserversource.Gvr(), src)). + //Must("Set sinkCACerts to non empty CA certs", source.ExpectCACerts(apiserversource.Gvr(), src)) return f } -func setupAccountAndRoleForPods(sacmName string) feature.StepFn { +func setupAccountAndRoleForApiserversource(sacmName string) feature.StepFn { return account_role.Install(sacmName, account_role.WithRole(sacmName+"-clusterrole"), account_role.WithRules(rbacv1.PolicyRule{ APIGroups: []string{""}, - Resources: []string{"events", "pods"}, - Verbs: []string{"get", "list", "watch"}, + Resources: []string{"events"}, + Verbs: []string{"get", "list", "watch", "create"}, }), ) } diff --git a/test/auth/oidc_test.go b/test/auth/oidc_test.go index cbfa38dde15..ae242badb27 100644 --- a/test/auth/oidc_test.go +++ b/test/auth/oidc_test.go @@ -39,7 +39,6 @@ import ( "knative.dev/eventing/test/rekt/resources/channel_template" "knative.dev/eventing/test/rekt/resources/parallel" "knative.dev/eventing/test/rekt/resources/sequence" - "knative.dev/reconciler-test/pkg/eventshub" ) func TestBrokerSupportsOIDC(t *testing.T) { @@ -142,7 +141,6 @@ func TestApiserversourceSendEventWithJWT(t *testing.T) { knative.WithTracingConfig, k8s.WithEventListener, environment.Managed(t), - eventshub.WithTLS(t), environment.WithPollTimings(4*time.Second, 12*time.Minute), ) diff --git a/test/rekt/resources/apiserversource/apiserversource.go b/test/rekt/resources/apiserversource/apiserversource.go index 5ae71b14154..3ace9b322e9 100644 --- a/test/rekt/resources/apiserversource/apiserversource.go +++ b/test/rekt/resources/apiserversource/apiserversource.go @@ -90,6 +90,7 @@ func WithSink(d *duckv1.Destination) manifest.CfgFn { ref := d.Ref uri := d.URI + //aud := d.Audience if d.CACerts != nil { // This is a multi-line string and should be indented accordingly. @@ -100,6 +101,9 @@ func WithSink(d *duckv1.Destination) manifest.CfgFn { if uri != nil { sink["uri"] = uri.String() } + + sink["audience"] = "my-sink-audience" + if ref != nil { if _, set := sink["ref"]; !set { sink["ref"] = map[string]interface{}{} From 88636541ad704eebd1da4afcdf4e39b48bb44cc6 Mon Sep 17 00:00:00 2001 From: Leo Li Date: Mon, 4 Dec 2023 12:25:51 -0500 Subject: [PATCH 12/62] Save the work progress, as everything is working right now. Next, will be cleaning up the codebase Signed-off-by: Leo Li --- pkg/reconciler/apiserversource/apiserversource.go | 15 ++++++++------- .../apiserversource/resources/receive_adapter.go | 6 +++--- .../resources/apiserversource/apiserversource.go | 5 +++-- .../apiserversource/apiserversource.yaml | 3 +++ 4 files changed, 17 insertions(+), 12 deletions(-) diff --git a/pkg/reconciler/apiserversource/apiserversource.go b/pkg/reconciler/apiserversource/apiserversource.go index b7b4a53a300..c0d3d6f56d0 100644 --- a/pkg/reconciler/apiserversource/apiserversource.go +++ b/pkg/reconciler/apiserversource/apiserversource.go @@ -122,6 +122,10 @@ func (r *Reconciler) ReconcileKind(ctx context.Context, source *v1.ApiServerSour logging.FromContext(ctx).Errorw("haha: try to display source sink ref", zap.Any("audience is", source.Spec.Sink.Audience)) logging.FromContext(ctx).Errorw("haha try to display sinkAddr Audience", zap.Any("audience is", sinkAddr.Audience)) + // The service account should already be created too + logging.FromContext(ctx).Errorw("haha: try to display the source OIDC service account", zap.Any("OIDC SA is", source.Spec.ServiceAccountName)) + logging.FromContext(ctx).Errorw("haha: try to display the source OIDC service account - Auth", zap.Any("OIDC SA is", source.Status.Auth.ServiceAccountName)) + // resolve namespaces to watch namespaces, err := r.namespacesFromSelector(source) if err != nil { @@ -212,12 +216,8 @@ func (r *Reconciler) createReceiveAdapter(ctx context.Context, src *v1.ApiServer fmt.Printf("haha sinkAddr.URL.String(): %v\n", sinkAddr.URL.String()) fmt.Printf("haha sinkAddr.audience: %v\n", sinkAddr.Audience) - var audience string - if sinkAddr.Audience != nil { - audience = *sinkAddr.Audience - } else { - audience = "ilovehaha" - } + fmt.Printf("haha show the OIDC service account name pointer: %v \n", src.Status.Auth.ServiceAccountName) + fmt.Printf("haha show the OIDC service account name string: %v \n", *src.Status.Auth.ServiceAccountName) // trying to figure out why audience is empty @@ -227,11 +227,12 @@ func (r *Reconciler) createReceiveAdapter(ctx context.Context, src *v1.ApiServer Labels: resources.Labels(src.Name), CACerts: sinkAddr.CACerts, SinkURI: sinkAddr.URL.String(), - Audience: audience, + Audience: sinkAddr.Audience, Configs: r.configs, Namespaces: namespaces, AllNamespaces: allNamespaces, } + expected, err := resources.MakeReceiveAdapter(&adapterArgs) if err != nil { return nil, err diff --git a/pkg/reconciler/apiserversource/resources/receive_adapter.go b/pkg/reconciler/apiserversource/resources/receive_adapter.go index 416f26230c5..a038b4e7344 100644 --- a/pkg/reconciler/apiserversource/resources/receive_adapter.go +++ b/pkg/reconciler/apiserversource/resources/receive_adapter.go @@ -42,7 +42,7 @@ type ReceiveAdapterArgs struct { Image string Source *v1.ApiServerSource Labels map[string]string - Audience string + Audience *string SinkURI string CACerts *string Configs reconcilersource.ConfigAccessor @@ -188,11 +188,11 @@ func makeEnv(args *ReceiveAdapterArgs) ([]corev1.EnvVar, error) { fmt.Printf("haha receive_adapter: trying to add the k_audience env var\n") fmt.Printf("haha receive_adapter: args.Audience is %v\n", args.Audience) - if args.Audience != "" { + if args.Audience != nil { fmt.Printf("haha receive_adapter: adding the k_audience env var\n") envs = append(envs, corev1.EnvVar{ Name: "K_AUDIENCE", - Value: args.Audience, + Value: *args.Audience, }) } diff --git a/test/rekt/resources/apiserversource/apiserversource.go b/test/rekt/resources/apiserversource/apiserversource.go index 3ace9b322e9..ef371984e85 100644 --- a/test/rekt/resources/apiserversource/apiserversource.go +++ b/test/rekt/resources/apiserversource/apiserversource.go @@ -90,7 +90,6 @@ func WithSink(d *duckv1.Destination) manifest.CfgFn { ref := d.Ref uri := d.URI - //aud := d.Audience if d.CACerts != nil { // This is a multi-line string and should be indented accordingly. @@ -102,7 +101,9 @@ func WithSink(d *duckv1.Destination) manifest.CfgFn { sink["uri"] = uri.String() } - sink["audience"] = "my-sink-audience" + if d.Audience != nil { + sink["audience"] = *d.Audience + } if ref != nil { if _, set := sink["ref"]; !set { diff --git a/test/rekt/resources/apiserversource/apiserversource.yaml b/test/rekt/resources/apiserversource/apiserversource.yaml index b0ad6d2ffac..c4ba4f02b37 100644 --- a/test/rekt/resources/apiserversource/apiserversource.yaml +++ b/test/rekt/resources/apiserversource/apiserversource.yaml @@ -83,4 +83,7 @@ spec: {{ if .sink.uri }} uri: {{ .sink.uri }} {{ end }} + { { if .sink.audience } } + audience: { { .sink.audience } } + { { end } } {{ end }} From 5b9fbc22d763648f98dfb1bc05aae4ebddc86ae4 Mon Sep 17 00:00:00 2001 From: Leo Li Date: Mon, 4 Dec 2023 23:02:33 -0500 Subject: [PATCH 13/62] Fix the format issue (wrong indentation) the yaml file Signed-off-by: Leo Li --- test/rekt/resources/apiserversource/apiserversource.yaml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/test/rekt/resources/apiserversource/apiserversource.yaml b/test/rekt/resources/apiserversource/apiserversource.yaml index c4ba4f02b37..57da274150b 100644 --- a/test/rekt/resources/apiserversource/apiserversource.yaml +++ b/test/rekt/resources/apiserversource/apiserversource.yaml @@ -83,7 +83,7 @@ spec: {{ if .sink.uri }} uri: {{ .sink.uri }} {{ end }} - { { if .sink.audience } } - audience: { { .sink.audience } } - { { end } } + {{ if .sink.audience }} + audience: {{ .sink.audience }} + {{ end }} {{ end }} From f49c7fcb251ea5190943579799f2981368816ca3 Mon Sep 17 00:00:00 2001 From: Leo Li Date: Tue, 5 Dec 2023 00:08:23 -0500 Subject: [PATCH 14/62] Refactored and test passed Signed-off-by: Leo Li --- pkg/auth/serviceaccount.go | 140 ------------ .../apiserversource/apiserversource.go | 216 +++++++++++++++++- .../resources/receive_adapter.go | 89 +++++++- 3 files changed, 299 insertions(+), 146 deletions(-) diff --git a/pkg/auth/serviceaccount.go b/pkg/auth/serviceaccount.go index e09bb2a428a..d81b7681a73 100644 --- a/pkg/auth/serviceaccount.go +++ b/pkg/auth/serviceaccount.go @@ -19,7 +19,6 @@ package auth import ( "context" "fmt" - rbacv1 "k8s.io/api/rbac/v1" "knative.dev/eventing/pkg/apis/feature" duckv1 "knative.dev/pkg/apis/duck/v1" pkgreconciler "knative.dev/pkg/reconciler" @@ -123,142 +122,3 @@ func SetupOIDCServiceAccount(ctx context.Context, flags feature.Flags, serviceAc return nil } -// EnsureOIDCServiceAccountRoleBindingExistsForResource -// makes sure the given resource has an OIDC service account role binding with -// an owner reference to the resource set. -func EnsureOIDCServiceAccountRoleBindingExistsForResource(ctx context.Context, kubeclient kubernetes.Interface, gvk schema.GroupVersionKind, objectMeta metav1.ObjectMeta, saName string) error { - logger := logging.FromContext(ctx) - logger.Errorf("haha: Initializing") - - roleName := fmt.Sprintf("create-oidc-token") - roleBindingName := fmt.Sprintf("create-oidc-token") - - logger.Errorf("haha: going to get role binding for %s", objectMeta.Name) - logger.Errorf("haha: role name %s", roleName) - logger.Errorf("haha: role binding name %s", roleBindingName) - - roleBinding, err := kubeclient.RbacV1().RoleBindings(objectMeta.Namespace).Get(ctx, roleBindingName, metav1.GetOptions{}) - - logger.Errorf("haha: got role binding for %s", roleBinding) - - logger.Errorf("haha: going to enter the if statement") - // If the resource doesn't exist, we'll create it. - if apierrs.IsNotFound(err) { - logging.FromContext(ctx).Debugw("Creating OIDC service account role binding", zap.Error(err)) - logger.Errorf("haha: creating role binding") - - // Create the "create-oidc-token" role - CreateRoleForServiceAccount(ctx, kubeclient, gvk, objectMeta) - - roleBinding = &rbacv1.RoleBinding{ - ObjectMeta: metav1.ObjectMeta{ - Name: roleBindingName, - Namespace: objectMeta.GetNamespace(), - Annotations: map[string]string{ - "description": fmt.Sprintf("Role Binding for OIDC Authentication for %s %q", gvk.GroupKind().Kind, objectMeta.Name), - }, - }, - RoleRef: rbacv1.RoleRef{ - APIGroup: "rbac.authorization.k8s.io", - Kind: "Role", - //objectMeta.Name + roleName - Name: fmt.Sprintf(roleName), - }, - Subjects: []rbacv1.Subject{ - { - Kind: "ServiceAccount", - Namespace: objectMeta.GetNamespace(), - // apiServerSource service account name, it is in the source.Spec, NOT in source.Auth - Name: saName, - }, - }, - } - - logger.Errorf("haha: role binding object created") - logger.Errorf("haha: role binding object %s", roleBinding) - - _, err = kubeclient.RbacV1().RoleBindings(objectMeta.Namespace).Create(ctx, roleBinding, metav1.CreateOptions{}) - if err != nil { - logger.Errorf("haha: error creating role binding") - logger.Errorf("haha: error %s", err) - return fmt.Errorf("could not create OIDC service account role binding %s/%s for %s: %w", objectMeta.Name, objectMeta.Namespace, gvk.Kind, err) - } - - return nil - } - - if err != nil { - logger.Errorf("haha: error getting role binding") - logger.Errorf("haha: error %s", err) - return fmt.Errorf("could not get OIDC service account role binding %s/%s for %s: %w", objectMeta.Name, objectMeta.Namespace, gvk.Kind, err) - - } - - if !metav1.IsControlledBy(&roleBinding.ObjectMeta, &objectMeta) { - logger.Errorf("haha: role binding not owned by") - logger.Errorf("haha: role binding %s", roleBinding) - return fmt.Errorf("role binding %s not owned by %s %s", roleBinding.Name, gvk.Kind, objectMeta.Name) - } - - return nil -} - -// Create the create-oidc-token role for the service account -func CreateRoleForServiceAccount(ctx context.Context, kubeclient kubernetes.Interface, gvk schema.GroupVersionKind, objectMeta metav1.ObjectMeta) error { - - logger := logging.FromContext(ctx) - logger.Errorf("haha: Initializing create role for service account") - - roleName := fmt.Sprintf("create-oidc-token") - logger.Errorf("haha: role name %s", roleName) - - role, err := kubeclient.RbacV1().Roles(objectMeta.Namespace).Get(ctx, roleName, metav1.GetOptions{}) - logger.Errorf("haha: got role %s", role) - - // If the resource doesn't exist, we'll create it. - if apierrs.IsNotFound(err) { - logging.FromContext(ctx).Debugw("Creating OIDC service account role", zap.Error(err)) - - logger.Errorf("haha: creating role") - - role = &rbacv1.Role{ - ObjectMeta: metav1.ObjectMeta{ - Name: roleName, - Namespace: objectMeta.GetNamespace(), - Annotations: map[string]string{ - "description": fmt.Sprintf("Role for OIDC Authentication for %s %q", gvk.GroupKind().Kind, objectMeta.Name), - }, - }, - Rules: []rbacv1.PolicyRule{ - rbacv1.PolicyRule{ - APIGroups: []string{""}, - - // serviceaccount name - ResourceNames: []string{GetOIDCServiceAccountNameForResource(gvk, objectMeta)}, - Resources: []string{"serviceaccounts/token"}, - Verbs: []string{"create"}, - }, - }, - } - - logger.Errorf("haha: role object created") - logger.Errorf("haha: role object %s", role) - - _, err = kubeclient.RbacV1().Roles(objectMeta.Namespace).Create(ctx, role, metav1.CreateOptions{}) - if err != nil { - logger.Errorf("haha: error creating role") - logger.Errorf("haha: error %s", err) - return fmt.Errorf("could not create OIDC service account role %s/%s for %s: %w", objectMeta.Name, objectMeta.Namespace, gvk.Kind, err) - } - - return nil - } - - if err != nil { - logger.Errorf("haha: error getting role") - logger.Errorf("haha: error getting role %s", err) - return fmt.Errorf("could not get OIDC service account role %s/%s for %s: %w", objectMeta.Name, objectMeta.Namespace, gvk.Kind, err) - - } - return nil -} diff --git a/pkg/reconciler/apiserversource/apiserversource.go b/pkg/reconciler/apiserversource/apiserversource.go index c0d3d6f56d0..e4263ec1045 100644 --- a/pkg/reconciler/apiserversource/apiserversource.go +++ b/pkg/reconciler/apiserversource/apiserversource.go @@ -20,6 +20,8 @@ import ( "context" "encoding/json" "fmt" + + apierrs "k8s.io/apimachinery/pkg/api/errors" "sort" "go.uber.org/zap" @@ -106,9 +108,25 @@ func (r *Reconciler) ReconcileKind(ctx context.Context, source *v1.ApiServerSour return err } - // Create the role and rolebinding + // Create the role logging.FromContext(ctx).Errorw("haha: About to enter the role access granting stage Creating role and rolebinding") - auth.EnsureOIDCServiceAccountRoleBindingExistsForResource(ctx, r.kubeClientSet, v1.SchemeGroupVersion.WithKind("ApiServerSource"), source.ObjectMeta, source.Spec.ServiceAccountName) + err := createOIDCRole(ctx,r.kubeClientSet,v1.SchemeGroupVersion.WithKind("ApiServerSource"), source.ObjectMeta) + + if err != nil{ + logging.FromContext(ctx).Errorw("Failed when creating the OIDC Role for ApiServerSource", zap.Error(err)) + return err + } + + // Create the rolebinding + + err = createOIDCRoleBinding(ctx,r.kubeClientSet,v1.SchemeGroupVersion.WithKind("ApiServerSource"),source.ObjectMeta, source.Spec.ServiceAccountName) + if err != nil{ + logging.FromContext(ctx).Errorw("Failed when creating the OIDC RoleBinding for ApiServerSource", zap.Error(err)) + return err + } + + + logging.FromContext(ctx).Errorw("haha: finished About to enter the role access granting stage Creating role and rolebinding") sinkAddr, err := r.sinkResolver.AddressableFromDestinationV1(ctx, *dest, source) @@ -372,3 +390,197 @@ func (r *Reconciler) createCloudEventAttributes(src *v1.ApiServerSource) ([]duck } // TODO: adding the rolebinding function to the resource folder and the role to the auth folder + +// createOIDCRole: this function will call resources package to get the role object +// and then pass to kubeclient to make the actual OIDC role +func createOIDCRole (ctx context.Context,kubeclient kubernetes.Interface , gvk schema.GroupVersionKind, objectMeta metav1.ObjectMeta) (error){ + + roleName := "create-oidc-token" + // First, create the role object + + //Second, call kubeclient and see whether the role exist or not + role, err := kubeclient.RbacV1().Roles(objectMeta.Namespace).Get(ctx, roleName, metav1.GetOptions{}) + logging.FromContext(ctx).Errorw("haha in the controller: role object %s", zap.Any("role",role)) + + if apierrs.IsNotFound(err) { + role,err := resources.MakeOIDCRole(ctx,gvk,objectMeta) + logging.FromContext(ctx).Errorw("haha in the controller: not found", zap.Error(err)) + // If the role does not exist, we will call kubeclient to create it + _, err = kubeclient.RbacV1().Roles(objectMeta.Namespace).Create(ctx, role, metav1.CreateOptions{}) + if err != nil { + return fmt.Errorf("could not create OIDC service account role %s/%s for %s: %w", objectMeta.Name, objectMeta.Namespace, gvk.Kind, err) + } + + } + + return nil + +} + + +// createOIDCRoleBinding: this function will call resources package to get the rolebinding object +// and then pass to kubeclient to make the actual OIDC rolebinding +func createOIDCRoleBinding (ctx context.Context, kubeclient kubernetes.Interface, gvk schema.GroupVersionKind, objectMeta metav1.ObjectMeta, saName string) (error) { + roleBindingName := "create-oidc-token" + // First, create the rolebinding object + + + // Second, call kubeclient and see whether the role exist or not + _, err := kubeclient.RbacV1().RoleBindings(objectMeta.Namespace).Get(ctx, roleBindingName, metav1.GetOptions{}) + + if apierrs.IsNotFound(err) { + roleBinding, err := resources.MakeOIDCRoleBinding(ctx, gvk, objectMeta, saName) + // If the role does not exist, we will call kubeclient to create it + _, err = kubeclient.RbacV1().RoleBindings(objectMeta.Namespace).Create(ctx, roleBinding, metav1.CreateOptions{}) + if err != nil { + return fmt.Errorf("could not create OIDC service account rolebinding %s/%s for %s: %w", objectMeta.Name, objectMeta.Namespace, gvk.Kind, err) + } + + } + return nil +} + + + + + + +// EnsureOIDCServiceAccountRoleBindingExistsForResource +// makes sure the given resource has an OIDC service account role binding with +// an owner reference to the resource set. +//func EnsureOIDCServiceAccountRoleBindingExistsForResource(ctx context.Context, kubeclient kubernetes.Interface, gvk schema.GroupVersionKind, objectMeta metav1.ObjectMeta, saName string) error { +// logger := logging.FromContext(ctx) +// logger.Errorf("haha: Initializing") +// +// roleName := fmt.Sprintf("create-oidc-token") +// roleBindingName := fmt.Sprintf("create-oidc-token") +// +// logger.Errorf("haha: going to get role binding for %s", objectMeta.Name) +// logger.Errorf("haha: role name %s", roleName) +// logger.Errorf("haha: role binding name %s", roleBindingName) +// +// roleBinding, err := kubeclient.RbacV1().RoleBindings(objectMeta.Namespace).Get(ctx, roleBindingName, metav1.GetOptions{}) +// +// logger.Errorf("haha: got role binding for %s", roleBinding) +// +// logger.Errorf("haha: going to enter the if statement") +// // If the resource doesn't exist, we'll create it. +// if apierrs.IsNotFound(err) { +// logging.FromContext(ctx).Debugw("Creating OIDC service account role binding", zap.Error(err)) +// logger.Errorf("haha: creating role binding") +// +// // Create the "create-oidc-token" role +// CreateRoleForServiceAccount(ctx, kubeclient, gvk, objectMeta) +// +// roleBinding = &rbacv1.RoleBinding{ +// ObjectMeta: metav1.ObjectMeta{ +// Name: roleBindingName, +// Namespace: objectMeta.GetNamespace(), +// Annotations: map[string]string{ +// "description": fmt.Sprintf("Role Binding for OIDC Authentication for %s %q", gvk.GroupKind().Kind, objectMeta.Name), +// }, +// }, +// RoleRef: rbacv1.RoleRef{ +// APIGroup: "rbac.authorization.k8s.io", +// Kind: "Role", +// //objectMeta.Name + roleName +// Name: fmt.Sprintf(roleName), +// }, +// Subjects: []rbacv1.Subject{ +// { +// Kind: "ServiceAccount", +// Namespace: objectMeta.GetNamespace(), +// // apiServerSource service account name, it is in the source.Spec, NOT in source.Auth +// Name: saName, +// }, +// }, +// } +// +// logger.Errorf("haha: role binding object created") +// logger.Errorf("haha: role binding object %s", roleBinding) +// +// _, err = kubeclient.RbacV1().RoleBindings(objectMeta.Namespace).Create(ctx, roleBinding, metav1.CreateOptions{}) +// if err != nil { +// logger.Errorf("haha: error creating role binding") +// logger.Errorf("haha: error %s", err) +// return fmt.Errorf("could not create OIDC service account role binding %s/%s for %s: %w", objectMeta.Name, objectMeta.Namespace, gvk.Kind, err) +// } +// +// return nil +// } +// +// if err != nil { +// logger.Errorf("haha: error getting role binding") +// logger.Errorf("haha: error %s", err) +// return fmt.Errorf("could not get OIDC service account role binding %s/%s for %s: %w", objectMeta.Name, objectMeta.Namespace, gvk.Kind, err) +// +// } +// +// if !metav1.IsControlledBy(&roleBinding.ObjectMeta, &objectMeta) { +// logger.Errorf("haha: role binding not owned by") +// logger.Errorf("haha: role binding %s", roleBinding) +// return fmt.Errorf("role binding %s not owned by %s %s", roleBinding.Name, gvk.Kind, objectMeta.Name) +// } +// +// return nil +//} +// +//// Create the create-oidc-token role for the service account +//func CreateRoleForServiceAccount(ctx context.Context, kubeclient kubernetes.Interface, gvk schema.GroupVersionKind, objectMeta metav1.ObjectMeta) error { +// +// logger := logging.FromContext(ctx) +// logger.Errorf("haha: Initializing create role for service account") +// +// roleName := fmt.Sprintf("create-oidc-token") +// logger.Errorf("haha: role name %s", roleName) +// +// role, err := kubeclient.RbacV1().Roles(objectMeta.Namespace).Get(ctx, roleName, metav1.GetOptions{}) +// logger.Errorf("haha: got role %s", role) +// +// // If the resource doesn't exist, we'll create it. +// if apierrs.IsNotFound(err) { +// logging.FromContext(ctx).Debugw("Creating OIDC service account role", zap.Error(err)) +// +// logger.Errorf("haha: creating role") +// +// role = &rbacv1.Role{ +// ObjectMeta: metav1.ObjectMeta{ +// Name: roleName, +// Namespace: objectMeta.GetNamespace(), +// Annotations: map[string]string{ +// "description": fmt.Sprintf("Role for OIDC Authentication for %s %q", gvk.GroupKind().Kind, objectMeta.Name), +// }, +// }, +// Rules: []rbacv1.PolicyRule{ +// rbacv1.PolicyRule{ +// APIGroups: []string{""}, +// +// // serviceaccount name +// ResourceNames: []string{auth.GetOIDCServiceAccountNameForResource(gvk, objectMeta)}, +// Resources: []string{"serviceaccounts/token"}, +// Verbs: []string{"create"}, +// }, +// }, +// } +// +// logger.Errorf("haha: role object created") +// logger.Errorf("haha: role object %s", role) +// +// _, err = kubeclient.RbacV1().Roles(objectMeta.Namespace).Create(ctx, role, metav1.CreateOptions{}) +// if err != nil { +// logger.Errorf("haha: error creating role") +// logger.Errorf("haha: error %s", err) +// return fmt.Errorf("could not create OIDC service account role %s/%s for %s: %w", objectMeta.Name, objectMeta.Namespace, gvk.Kind, err) +// } +// +// return nil +// } +// +// if err != nil { +// logger.Errorf("haha: error getting role") +// logger.Errorf("haha: error getting role %s", err) +// return fmt.Errorf("could not get OIDC service account role %s/%s for %s: %w", objectMeta.Name, objectMeta.Namespace, gvk.Kind, err) +// +// } +// return nil +//} diff --git a/pkg/reconciler/apiserversource/resources/receive_adapter.go b/pkg/reconciler/apiserversource/resources/receive_adapter.go index a038b4e7344..54c0f691432 100644 --- a/pkg/reconciler/apiserversource/resources/receive_adapter.go +++ b/pkg/reconciler/apiserversource/resources/receive_adapter.go @@ -17,15 +17,19 @@ limitations under the License. package resources import ( + "context" "encoding/json" "fmt" appsv1 "k8s.io/api/apps/v1" corev1 "k8s.io/api/core/v1" + rbacv1 "k8s.io/api/rbac/v1" "k8s.io/apimachinery/pkg/api/meta" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime/schema" "k8s.io/apimachinery/pkg/util/intstr" "knative.dev/eventing/pkg/adapter/v2" + "knative.dev/eventing/pkg/auth" + "knative.dev/pkg/logging" "knative.dev/pkg/kmeta" "knative.dev/pkg/ptr" @@ -50,6 +54,84 @@ type ReceiveAdapterArgs struct { AllNamespaces bool } +// MakeOIDCRole will return the role object config for generating the JWT token +func MakeOIDCRole(ctx context.Context, gvk schema.GroupVersionKind, objectMeta metav1.ObjectMeta) (*rbacv1.Role, error) { + logger := logging.FromContext(ctx) + logger.Errorf("haha: Initializing create role for service account") + + roleName := fmt.Sprintf("create-oidc-token") + logger.Errorf("haha: role name %s", roleName) + + logger.Errorf("haha: creating role") + + return &rbacv1.Role{ + ObjectMeta: metav1.ObjectMeta{ + Name: roleName, + Namespace: objectMeta.GetNamespace(), + Annotations: map[string]string{ + "description": fmt.Sprintf("Role for OIDC Authentication for %s %q", gvk.GroupKind().Kind, objectMeta.Name), + }, + }, + Rules: []rbacv1.PolicyRule{ + rbacv1.PolicyRule{ + APIGroups: []string{""}, + ResourceNames: []string{auth.GetOIDCServiceAccountNameForResource(gvk, objectMeta)}, + Resources: []string{"serviceaccounts/token"}, + Verbs: []string{"create"}, + }, + }, + }, nil + + +} + +// MakeOIDCRoleBinding will return the rolebinding object for generating the JWT token +// So that ApiServerSource's service account have access to create the JWT token for it's OIDC service account and the target audience +// Note: it is in the source.Spec, NOT in source.Auth +func MakeOIDCRoleBinding(ctx context.Context, gvk schema.GroupVersionKind, objectMeta metav1.ObjectMeta, saName string) (*rbacv1.RoleBinding, error) { + logger := logging.FromContext(ctx) + logger.Errorf("haha: Initializing") + + roleName := fmt.Sprintf("create-oidc-token") + roleBindingName := fmt.Sprintf("create-oidc-token") + + logger.Errorf("haha: going to get role binding for %s", objectMeta.Name) + logger.Errorf("haha: role name %s", roleName) + logger.Errorf("haha: role binding name %s", roleBindingName) + + logger.Errorf("haha: creating role binding") + + roleBinding := &rbacv1.RoleBinding{ + ObjectMeta: metav1.ObjectMeta{ + Name: roleBindingName, + Namespace: objectMeta.GetNamespace(), + Annotations: map[string]string{ + "description": fmt.Sprintf("Role Binding for OIDC Authentication for %s %q", gvk.GroupKind().Kind, objectMeta.Name), + }, + }, + RoleRef: rbacv1.RoleRef{ + APIGroup: "rbac.authorization.k8s.io", + Kind: "Role", + //objectMeta.Name + roleName + Name: fmt.Sprintf(roleName), + }, + Subjects: []rbacv1.Subject{ + { + Kind: "ServiceAccount", + Namespace: objectMeta.GetNamespace(), + //Note: apiServerSource service account name, it is in the source.Spec, NOT in source.Auth + Name: saName, + }, + }, + } + + logger.Errorf("haha: role binding object created") + logger.Errorf("haha: role binding object %s", roleBinding) + + return roleBinding, nil + +} + // MakeReceiveAdapter generates (but does not insert into K8s) the Receive Adapter Deployment for // ApiServer Sources. func MakeReceiveAdapter(args *ReceiveAdapterArgs) (*appsv1.Deployment, error) { @@ -172,11 +254,10 @@ func makeEnv(args *ReceiveAdapterArgs) ([]corev1.EnvVar, error) { }, { Name: "METRICS_DOMAIN", Value: "knative.dev/eventing", + }, { + Name: "K_OIDC_SERVICE_ACCOUNT", + Value: *args.Source.Status.Auth.ServiceAccountName, }, - { - Name: "K_OIDC_SERVICE_ACCOUNT", - Value: *args.Source.Status.Auth.ServiceAccountName, - }, } if args.CACerts != nil { From 012dece8aa76398df30be76dff1fff33dc8ca16b Mon Sep 17 00:00:00 2001 From: Leo Li Date: Tue, 5 Dec 2023 01:01:26 -0500 Subject: [PATCH 15/62] Refactored and test passed Signed-off-by: Leo Li --- pkg/adapter/v2/cloudevents.go | 15 ++----- pkg/adapter/v2/config.go | 14 ++++--- .../apiserversource/apiserversource.go | 42 +++++++------------ .../resources/receive_adapter.go | 14 +++++-- 4 files changed, 38 insertions(+), 47 deletions(-) diff --git a/pkg/adapter/v2/cloudevents.go b/pkg/adapter/v2/cloudevents.go index 2a662815891..07e58a06bce 100644 --- a/pkg/adapter/v2/cloudevents.go +++ b/pkg/adapter/v2/cloudevents.go @@ -233,7 +233,7 @@ type client struct { oidcTokenProvider *auth.OIDCTokenProvider audience string - serviceAccountName types.NamespacedName + serviceAccountName *types.NamespacedName } func (c *client) CloseIdleConnections() { @@ -247,19 +247,12 @@ func (c *client) Send(ctx context.Context, out event.Event) protocol.Result { c.applyOverrides(&out) logger := logging.FromContext(ctx) - logger.Errorf("haha send: trying to execute Send function") - - logger.Errorf("haha send: print service account name: %s", c.serviceAccountName.Name) - logger.Errorf("haha send: print service account namespace: %s", c.serviceAccountName.Namespace) - //logger.Errorf("haha send: print audience: %s", c.audience) - //logger.Errorf("haha send: print the audience, and audience is a string pointer: %s", *c.audience) - logger.Errorf("haha send: conclude, now going to generate the jwt token") // If the sink has audience, then we need to request the JWT token - if c.audience != "" { + if c.audience != "" && c.serviceAccountName != nil{ // Request the JWT token for the given service account //jwt, err := c.oidcTokenProvider.GetJWT(c.serviceAccountName, *c.audience) - jwt, err := c.oidcTokenProvider.GetJWT(c.serviceAccountName, c.audience) + jwt, err := c.oidcTokenProvider.GetJWT(*c.serviceAccountName, c.audience) logger.Errorf("haha send: print jwt: %s", jwt) logger.Errorf("haha send: print err: %s", err) @@ -295,7 +288,7 @@ func (c *client) Request(ctx context.Context, out event.Event) (*event.Event, pr // If the sink has audience, then we need to request the JWT token //if c.audience != nil{ // Request the JWT token for the given service account - jwt, err := c.oidcTokenProvider.GetJWT(c.serviceAccountName, "my-sink-audience") + jwt, err := c.oidcTokenProvider.GetJWT(*c.serviceAccountName, "my-sink-audience") logger.Errorf("haha send: print jwt: %s", jwt) logger.Errorf("haha send: print err: %s", err) diff --git a/pkg/adapter/v2/config.go b/pkg/adapter/v2/config.go index 9bde95e237e..772347caf70 100644 --- a/pkg/adapter/v2/config.go +++ b/pkg/adapter/v2/config.go @@ -126,7 +126,7 @@ type EnvConfigAccessor interface { // Get the audience of the target sink. GetAudience() string - GetServiceAccountName() types.NamespacedName + GetServiceAccountName() *types.NamespacedName // Get the namespace of the adapter. GetNamespace() string @@ -205,11 +205,15 @@ func (e *EnvConfig) GetSink() string { return e.Sink } -func (e *EnvConfig) GetServiceAccountName() types.NamespacedName { +func (e *EnvConfig) GetServiceAccountName() *types.NamespacedName { - return types.NamespacedName{ - Namespace: e.Namespace, - Name: *e.ServiceAccountName, + if e.ServiceAccountName != nil { + return &types.NamespacedName{ + Namespace: e.Namespace, + Name: *e.ServiceAccountName, + } + }else { + return nil } } diff --git a/pkg/reconciler/apiserversource/apiserversource.go b/pkg/reconciler/apiserversource/apiserversource.go index e4263ec1045..f527aa125dd 100644 --- a/pkg/reconciler/apiserversource/apiserversource.go +++ b/pkg/reconciler/apiserversource/apiserversource.go @@ -108,21 +108,23 @@ func (r *Reconciler) ReconcileKind(ctx context.Context, source *v1.ApiServerSour return err } - // Create the role - logging.FromContext(ctx).Errorw("haha: About to enter the role access granting stage Creating role and rolebinding") - err := createOIDCRole(ctx,r.kubeClientSet,v1.SchemeGroupVersion.WithKind("ApiServerSource"), source.ObjectMeta) + if featureFlags.IsOIDCAuthentication() { + // Create the role + logging.FromContext(ctx).Errorw("haha: About to enter the role access granting stage Creating role and rolebinding") + err := createOIDCRole(ctx, r.kubeClientSet, v1.SchemeGroupVersion.WithKind("ApiServerSource"), source.ObjectMeta) - if err != nil{ - logging.FromContext(ctx).Errorw("Failed when creating the OIDC Role for ApiServerSource", zap.Error(err)) - return err - } + if err != nil { + logging.FromContext(ctx).Errorw("Failed when creating the OIDC Role for ApiServerSource", zap.Error(err)) + return err + } - // Create the rolebinding + // Create the rolebinding - err = createOIDCRoleBinding(ctx,r.kubeClientSet,v1.SchemeGroupVersion.WithKind("ApiServerSource"),source.ObjectMeta, source.Spec.ServiceAccountName) - if err != nil{ - logging.FromContext(ctx).Errorw("Failed when creating the OIDC RoleBinding for ApiServerSource", zap.Error(err)) - return err + err = createOIDCRoleBinding(ctx, r.kubeClientSet, v1.SchemeGroupVersion.WithKind("ApiServerSource"), source.ObjectMeta, source.Spec.ServiceAccountName) + if err != nil { + logging.FromContext(ctx).Errorw("Failed when creating the OIDC RoleBinding for ApiServerSource", zap.Error(err)) + return err + } } @@ -136,14 +138,6 @@ func (r *Reconciler) ReconcileKind(ctx context.Context, source *v1.ApiServerSour } source.Status.MarkSink(sinkAddr) - // The audience should already be specified - logging.FromContext(ctx).Errorw("haha: try to display source sink ref", zap.Any("audience is", source.Spec.Sink.Audience)) - logging.FromContext(ctx).Errorw("haha try to display sinkAddr Audience", zap.Any("audience is", sinkAddr.Audience)) - - // The service account should already be created too - logging.FromContext(ctx).Errorw("haha: try to display the source OIDC service account", zap.Any("OIDC SA is", source.Spec.ServiceAccountName)) - logging.FromContext(ctx).Errorw("haha: try to display the source OIDC service account - Auth", zap.Any("OIDC SA is", source.Status.Auth.ServiceAccountName)) - // resolve namespaces to watch namespaces, err := r.namespacesFromSelector(source) if err != nil { @@ -229,14 +223,6 @@ func (r *Reconciler) createReceiveAdapter(ctx context.Context, src *v1.ApiServer // return nil, err // } - fmt.Printf("haha sinkAddr: %v\n", sinkAddr) - fmt.Printf("haha sinkAddr.URL: %v\n", sinkAddr.URL) - fmt.Printf("haha sinkAddr.URL.String(): %v\n", sinkAddr.URL.String()) - fmt.Printf("haha sinkAddr.audience: %v\n", sinkAddr.Audience) - - fmt.Printf("haha show the OIDC service account name pointer: %v \n", src.Status.Auth.ServiceAccountName) - fmt.Printf("haha show the OIDC service account name string: %v \n", *src.Status.Auth.ServiceAccountName) - // trying to figure out why audience is empty adapterArgs := resources.ReceiveAdapterArgs{ diff --git a/pkg/reconciler/apiserversource/resources/receive_adapter.go b/pkg/reconciler/apiserversource/resources/receive_adapter.go index 54c0f691432..c07a3f666dc 100644 --- a/pkg/reconciler/apiserversource/resources/receive_adapter.go +++ b/pkg/reconciler/apiserversource/resources/receive_adapter.go @@ -254,9 +254,6 @@ func makeEnv(args *ReceiveAdapterArgs) ([]corev1.EnvVar, error) { }, { Name: "METRICS_DOMAIN", Value: "knative.dev/eventing", - }, { - Name: "K_OIDC_SERVICE_ACCOUNT", - Value: *args.Source.Status.Auth.ServiceAccountName, }, } @@ -277,6 +274,17 @@ func makeEnv(args *ReceiveAdapterArgs) ([]corev1.EnvVar, error) { }) } + if args.Source.Status.Auth != nil { + //, { + //Name: "K_OIDC_SERVICE_ACCOUNT", + // Value: *args.Source.Status.Auth.ServiceAccountName, + //}, + envs = append(envs, corev1.EnvVar{ + Name: "K_OIDC_SERVICE_ACCOUNT", + Value: *args.Source.Status.Auth.ServiceAccountName, + }) + } + envs = append(envs, args.Configs.ToEnvVars()...) if args.Source.Spec.CloudEventOverrides != nil { From fb01ddea05cc2d8641d3cc17d770d4a94b8f8ea4 Mon Sep 17 00:00:00 2001 From: Leo Li Date: Tue, 5 Dec 2023 01:06:41 -0500 Subject: [PATCH 16/62] Remove all the logs Signed-off-by: Leo Li --- pkg/adapter/v2/cloudevents.go | 39 ++-- pkg/adapter/v2/config.go | 2 +- pkg/auth/serviceaccount.go | 1 - .../apiserversource/apiserversource.go | 184 ++---------------- .../resources/receive_adapter.go | 72 ++----- 5 files changed, 46 insertions(+), 252 deletions(-) diff --git a/pkg/adapter/v2/cloudevents.go b/pkg/adapter/v2/cloudevents.go index 07e58a06bce..a61f4d390f0 100644 --- a/pkg/adapter/v2/cloudevents.go +++ b/pkg/adapter/v2/cloudevents.go @@ -23,7 +23,6 @@ import ( "k8s.io/apimachinery/pkg/types" "knative.dev/eventing/pkg/auth" - "knative.dev/pkg/logging" nethttp "net/http" "net/url" "time" @@ -246,17 +245,10 @@ var _ cloudevents.Client = (*client)(nil) func (c *client) Send(ctx context.Context, out event.Event) protocol.Result { c.applyOverrides(&out) - logger := logging.FromContext(ctx) - - // If the sink has audience, then we need to request the JWT token - if c.audience != "" && c.serviceAccountName != nil{ + // If the sink has audience and the OIDC service account, then we need to request the JWT token + if c.audience != "" && c.serviceAccountName != nil { // Request the JWT token for the given service account - //jwt, err := c.oidcTokenProvider.GetJWT(c.serviceAccountName, *c.audience) jwt, err := c.oidcTokenProvider.GetJWT(*c.serviceAccountName, c.audience) - - logger.Errorf("haha send: print jwt: %s", jwt) - logger.Errorf("haha send: print err: %s", err) - if err != nil { return protocol.NewResult("%w", err) } @@ -276,22 +268,19 @@ func (c *client) Send(ctx context.Context, out event.Event) protocol.Result { func (c *client) Request(ctx context.Context, out event.Event) (*event.Event, protocol.Result) { c.applyOverrides(&out) - // If the sink has audience, then we need to request the JWT token - logger := logging.FromContext(ctx) - logger.Errorf("haha send: trying to execute Send function") - - logger.Errorf("haha req: print service account name: %s", c.serviceAccountName.Name) - logger.Errorf("haha req: print service account namespace: %s", c.serviceAccountName.Namespace) - //logger.Errorf("haha req: print audience: %s", c.audience) - logger.Errorf("haha req: conclude, now going to generate the jwt token") - - // If the sink has audience, then we need to request the JWT token - //if c.audience != nil{ - // Request the JWT token for the given service account - jwt, err := c.oidcTokenProvider.GetJWT(*c.serviceAccountName, "my-sink-audience") + // If the sink has audience and the OIDC service account, then we need to request the JWT token + if c.audience != "" && c.serviceAccountName != nil { + // Request the JWT token for the given service account + jwt, err := c.oidcTokenProvider.GetJWT(*c.serviceAccountName, c.audience) + if err != nil { + return nil, protocol.NewResult("%w", err) + } - logger.Errorf("haha send: print jwt: %s", jwt) - logger.Errorf("haha send: print err: %s", err) + // Appending the auth token to the outgoing request + headers := http.HeaderFrom(ctx) + headers.Set("Authorization", fmt.Sprintf("Bearer %s", jwt)) + ctx = http.WithCustomHeader(ctx, headers) + } resp, res := c.ceClient.Request(ctx, out) c.reportMetrics(ctx, out, res) diff --git a/pkg/adapter/v2/config.go b/pkg/adapter/v2/config.go index 772347caf70..2302e420b5c 100644 --- a/pkg/adapter/v2/config.go +++ b/pkg/adapter/v2/config.go @@ -212,7 +212,7 @@ func (e *EnvConfig) GetServiceAccountName() *types.NamespacedName { Namespace: e.Namespace, Name: *e.ServiceAccountName, } - }else { + } else { return nil } } diff --git a/pkg/auth/serviceaccount.go b/pkg/auth/serviceaccount.go index d81b7681a73..650c843269c 100644 --- a/pkg/auth/serviceaccount.go +++ b/pkg/auth/serviceaccount.go @@ -121,4 +121,3 @@ func SetupOIDCServiceAccount(ctx context.Context, flags feature.Flags, serviceAc } return nil } - diff --git a/pkg/reconciler/apiserversource/apiserversource.go b/pkg/reconciler/apiserversource/apiserversource.go index f527aa125dd..479386388d4 100644 --- a/pkg/reconciler/apiserversource/apiserversource.go +++ b/pkg/reconciler/apiserversource/apiserversource.go @@ -21,9 +21,10 @@ import ( "encoding/json" "fmt" - apierrs "k8s.io/apimachinery/pkg/api/errors" "sort" + apierrs "k8s.io/apimachinery/pkg/api/errors" + "go.uber.org/zap" appsv1 "k8s.io/api/apps/v1" authorizationv1 "k8s.io/api/authorization/v1" @@ -110,7 +111,6 @@ func (r *Reconciler) ReconcileKind(ctx context.Context, source *v1.ApiServerSour if featureFlags.IsOIDCAuthentication() { // Create the role - logging.FromContext(ctx).Errorw("haha: About to enter the role access granting stage Creating role and rolebinding") err := createOIDCRole(ctx, r.kubeClientSet, v1.SchemeGroupVersion.WithKind("ApiServerSource"), source.ObjectMeta) if err != nil { @@ -119,7 +119,6 @@ func (r *Reconciler) ReconcileKind(ctx context.Context, source *v1.ApiServerSour } // Create the rolebinding - err = createOIDCRoleBinding(ctx, r.kubeClientSet, v1.SchemeGroupVersion.WithKind("ApiServerSource"), source.ObjectMeta, source.Spec.ServiceAccountName) if err != nil { logging.FromContext(ctx).Errorw("Failed when creating the OIDC RoleBinding for ApiServerSource", zap.Error(err)) @@ -127,10 +126,6 @@ func (r *Reconciler) ReconcileKind(ctx context.Context, source *v1.ApiServerSour } } - - - - logging.FromContext(ctx).Errorw("haha: finished About to enter the role access granting stage Creating role and rolebinding") sinkAddr, err := r.sinkResolver.AddressableFromDestinationV1(ctx, *dest, source) if err != nil { source.Status.MarkNoSink("NotFound", "") @@ -160,11 +155,8 @@ func (r *Reconciler) ReconcileKind(ctx context.Context, source *v1.ApiServerSour return err } - logging.FromContext(ctx).Debugw("haha: Receive adapter created", zap.Any("receiveAdapter", ra)) source.Status.PropagateDeploymentAvailability(ra) - logging.FromContext(ctx).Debugw("haha: Creating CloudEventAttributes") - cloudEventAttributes, err := r.createCloudEventAttributes(source) if err != nil { logging.FromContext(ctx).Errorw("Unable to create CloudEventAttributes", zap.Error(err)) @@ -292,10 +284,8 @@ func (r *Reconciler) runAccessCheck(ctx context.Context, src *v1.ApiServerSource // Run the basic service account access check (This is not OIDC service account) user := "system:serviceaccount:" + src.Namespace + ":" if src.Spec.ServiceAccountName == "" { - logging.FromContext(ctx).Debugw("haha No ServiceAccountName specified, using default") user += "default" } else { - logging.FromContext(ctx).Debugw("haha Using ServiceAccountName", zap.String("ServiceAccountName", src.Spec.ServiceAccountName)) user += src.Spec.ServiceAccountName } @@ -379,23 +369,19 @@ func (r *Reconciler) createCloudEventAttributes(src *v1.ApiServerSource) ([]duck // createOIDCRole: this function will call resources package to get the role object // and then pass to kubeclient to make the actual OIDC role -func createOIDCRole (ctx context.Context,kubeclient kubernetes.Interface , gvk schema.GroupVersionKind, objectMeta metav1.ObjectMeta) (error){ - +func createOIDCRole(ctx context.Context, kubeclient kubernetes.Interface, gvk schema.GroupVersionKind, objectMeta metav1.ObjectMeta) error { roleName := "create-oidc-token" - // First, create the role object - //Second, call kubeclient and see whether the role exist or not - role, err := kubeclient.RbacV1().Roles(objectMeta.Namespace).Get(ctx, roleName, metav1.GetOptions{}) - logging.FromContext(ctx).Errorw("haha in the controller: role object %s", zap.Any("role",role)) + //Call kubeclient and see whether the role exist or not + _, err := kubeclient.RbacV1().Roles(objectMeta.Namespace).Get(ctx, roleName, metav1.GetOptions{}) if apierrs.IsNotFound(err) { - role,err := resources.MakeOIDCRole(ctx,gvk,objectMeta) - logging.FromContext(ctx).Errorw("haha in the controller: not found", zap.Error(err)) + role, err := resources.MakeOIDCRole(ctx, gvk, objectMeta) // If the role does not exist, we will call kubeclient to create it _, err = kubeclient.RbacV1().Roles(objectMeta.Namespace).Create(ctx, role, metav1.CreateOptions{}) - if err != nil { - return fmt.Errorf("could not create OIDC service account role %s/%s for %s: %w", objectMeta.Name, objectMeta.Namespace, gvk.Kind, err) - } + if err != nil { + return fmt.Errorf("could not create OIDC service account role %s/%s for %s: %w", objectMeta.Name, objectMeta.Namespace, gvk.Kind, err) + } } @@ -403,15 +389,12 @@ func createOIDCRole (ctx context.Context,kubeclient kubernetes.Interface , gvk s } - // createOIDCRoleBinding: this function will call resources package to get the rolebinding object // and then pass to kubeclient to make the actual OIDC rolebinding -func createOIDCRoleBinding (ctx context.Context, kubeclient kubernetes.Interface, gvk schema.GroupVersionKind, objectMeta metav1.ObjectMeta, saName string) (error) { +func createOIDCRoleBinding(ctx context.Context, kubeclient kubernetes.Interface, gvk schema.GroupVersionKind, objectMeta metav1.ObjectMeta, saName string) error { roleBindingName := "create-oidc-token" - // First, create the rolebinding object - - // Second, call kubeclient and see whether the role exist or not + // Call kubeclient and see whether the roleBinding exist or not _, err := kubeclient.RbacV1().RoleBindings(objectMeta.Namespace).Get(ctx, roleBindingName, metav1.GetOptions{}) if apierrs.IsNotFound(err) { @@ -425,148 +408,3 @@ func createOIDCRoleBinding (ctx context.Context, kubeclient kubernetes.Interface } return nil } - - - - - - -// EnsureOIDCServiceAccountRoleBindingExistsForResource -// makes sure the given resource has an OIDC service account role binding with -// an owner reference to the resource set. -//func EnsureOIDCServiceAccountRoleBindingExistsForResource(ctx context.Context, kubeclient kubernetes.Interface, gvk schema.GroupVersionKind, objectMeta metav1.ObjectMeta, saName string) error { -// logger := logging.FromContext(ctx) -// logger.Errorf("haha: Initializing") -// -// roleName := fmt.Sprintf("create-oidc-token") -// roleBindingName := fmt.Sprintf("create-oidc-token") -// -// logger.Errorf("haha: going to get role binding for %s", objectMeta.Name) -// logger.Errorf("haha: role name %s", roleName) -// logger.Errorf("haha: role binding name %s", roleBindingName) -// -// roleBinding, err := kubeclient.RbacV1().RoleBindings(objectMeta.Namespace).Get(ctx, roleBindingName, metav1.GetOptions{}) -// -// logger.Errorf("haha: got role binding for %s", roleBinding) -// -// logger.Errorf("haha: going to enter the if statement") -// // If the resource doesn't exist, we'll create it. -// if apierrs.IsNotFound(err) { -// logging.FromContext(ctx).Debugw("Creating OIDC service account role binding", zap.Error(err)) -// logger.Errorf("haha: creating role binding") -// -// // Create the "create-oidc-token" role -// CreateRoleForServiceAccount(ctx, kubeclient, gvk, objectMeta) -// -// roleBinding = &rbacv1.RoleBinding{ -// ObjectMeta: metav1.ObjectMeta{ -// Name: roleBindingName, -// Namespace: objectMeta.GetNamespace(), -// Annotations: map[string]string{ -// "description": fmt.Sprintf("Role Binding for OIDC Authentication for %s %q", gvk.GroupKind().Kind, objectMeta.Name), -// }, -// }, -// RoleRef: rbacv1.RoleRef{ -// APIGroup: "rbac.authorization.k8s.io", -// Kind: "Role", -// //objectMeta.Name + roleName -// Name: fmt.Sprintf(roleName), -// }, -// Subjects: []rbacv1.Subject{ -// { -// Kind: "ServiceAccount", -// Namespace: objectMeta.GetNamespace(), -// // apiServerSource service account name, it is in the source.Spec, NOT in source.Auth -// Name: saName, -// }, -// }, -// } -// -// logger.Errorf("haha: role binding object created") -// logger.Errorf("haha: role binding object %s", roleBinding) -// -// _, err = kubeclient.RbacV1().RoleBindings(objectMeta.Namespace).Create(ctx, roleBinding, metav1.CreateOptions{}) -// if err != nil { -// logger.Errorf("haha: error creating role binding") -// logger.Errorf("haha: error %s", err) -// return fmt.Errorf("could not create OIDC service account role binding %s/%s for %s: %w", objectMeta.Name, objectMeta.Namespace, gvk.Kind, err) -// } -// -// return nil -// } -// -// if err != nil { -// logger.Errorf("haha: error getting role binding") -// logger.Errorf("haha: error %s", err) -// return fmt.Errorf("could not get OIDC service account role binding %s/%s for %s: %w", objectMeta.Name, objectMeta.Namespace, gvk.Kind, err) -// -// } -// -// if !metav1.IsControlledBy(&roleBinding.ObjectMeta, &objectMeta) { -// logger.Errorf("haha: role binding not owned by") -// logger.Errorf("haha: role binding %s", roleBinding) -// return fmt.Errorf("role binding %s not owned by %s %s", roleBinding.Name, gvk.Kind, objectMeta.Name) -// } -// -// return nil -//} -// -//// Create the create-oidc-token role for the service account -//func CreateRoleForServiceAccount(ctx context.Context, kubeclient kubernetes.Interface, gvk schema.GroupVersionKind, objectMeta metav1.ObjectMeta) error { -// -// logger := logging.FromContext(ctx) -// logger.Errorf("haha: Initializing create role for service account") -// -// roleName := fmt.Sprintf("create-oidc-token") -// logger.Errorf("haha: role name %s", roleName) -// -// role, err := kubeclient.RbacV1().Roles(objectMeta.Namespace).Get(ctx, roleName, metav1.GetOptions{}) -// logger.Errorf("haha: got role %s", role) -// -// // If the resource doesn't exist, we'll create it. -// if apierrs.IsNotFound(err) { -// logging.FromContext(ctx).Debugw("Creating OIDC service account role", zap.Error(err)) -// -// logger.Errorf("haha: creating role") -// -// role = &rbacv1.Role{ -// ObjectMeta: metav1.ObjectMeta{ -// Name: roleName, -// Namespace: objectMeta.GetNamespace(), -// Annotations: map[string]string{ -// "description": fmt.Sprintf("Role for OIDC Authentication for %s %q", gvk.GroupKind().Kind, objectMeta.Name), -// }, -// }, -// Rules: []rbacv1.PolicyRule{ -// rbacv1.PolicyRule{ -// APIGroups: []string{""}, -// -// // serviceaccount name -// ResourceNames: []string{auth.GetOIDCServiceAccountNameForResource(gvk, objectMeta)}, -// Resources: []string{"serviceaccounts/token"}, -// Verbs: []string{"create"}, -// }, -// }, -// } -// -// logger.Errorf("haha: role object created") -// logger.Errorf("haha: role object %s", role) -// -// _, err = kubeclient.RbacV1().Roles(objectMeta.Namespace).Create(ctx, role, metav1.CreateOptions{}) -// if err != nil { -// logger.Errorf("haha: error creating role") -// logger.Errorf("haha: error %s", err) -// return fmt.Errorf("could not create OIDC service account role %s/%s for %s: %w", objectMeta.Name, objectMeta.Namespace, gvk.Kind, err) -// } -// -// return nil -// } -// -// if err != nil { -// logger.Errorf("haha: error getting role") -// logger.Errorf("haha: error getting role %s", err) -// return fmt.Errorf("could not get OIDC service account role %s/%s for %s: %w", objectMeta.Name, objectMeta.Namespace, gvk.Kind, err) -// -// } -// return nil -//} diff --git a/pkg/reconciler/apiserversource/resources/receive_adapter.go b/pkg/reconciler/apiserversource/resources/receive_adapter.go index c07a3f666dc..e3a9d2fa910 100644 --- a/pkg/reconciler/apiserversource/resources/receive_adapter.go +++ b/pkg/reconciler/apiserversource/resources/receive_adapter.go @@ -29,8 +29,6 @@ import ( "k8s.io/apimachinery/pkg/util/intstr" "knative.dev/eventing/pkg/adapter/v2" "knative.dev/eventing/pkg/auth" - "knative.dev/pkg/logging" - "knative.dev/pkg/kmeta" "knative.dev/pkg/ptr" "knative.dev/pkg/system" @@ -56,32 +54,25 @@ type ReceiveAdapterArgs struct { // MakeOIDCRole will return the role object config for generating the JWT token func MakeOIDCRole(ctx context.Context, gvk schema.GroupVersionKind, objectMeta metav1.ObjectMeta) (*rbacv1.Role, error) { - logger := logging.FromContext(ctx) - logger.Errorf("haha: Initializing create role for service account") - roleName := fmt.Sprintf("create-oidc-token") - logger.Errorf("haha: role name %s", roleName) - - logger.Errorf("haha: creating role") return &rbacv1.Role{ - ObjectMeta: metav1.ObjectMeta{ - Name: roleName, - Namespace: objectMeta.GetNamespace(), - Annotations: map[string]string{ - "description": fmt.Sprintf("Role for OIDC Authentication for %s %q", gvk.GroupKind().Kind, objectMeta.Name), - }, - }, - Rules: []rbacv1.PolicyRule{ - rbacv1.PolicyRule{ - APIGroups: []string{""}, - ResourceNames: []string{auth.GetOIDCServiceAccountNameForResource(gvk, objectMeta)}, - Resources: []string{"serviceaccounts/token"}, - Verbs: []string{"create"}, - }, - }, - }, nil - + ObjectMeta: metav1.ObjectMeta{ + Name: roleName, + Namespace: objectMeta.GetNamespace(), + Annotations: map[string]string{ + "description": fmt.Sprintf("Role for OIDC Authentication for %s %q", gvk.GroupKind().Kind, objectMeta.Name), + }, + }, + Rules: []rbacv1.PolicyRule{ + rbacv1.PolicyRule{ + APIGroups: []string{""}, + ResourceNames: []string{auth.GetOIDCServiceAccountNameForResource(gvk, objectMeta)}, + Resources: []string{"serviceaccounts/token"}, + Verbs: []string{"create"}, + }, + }, + }, nil } @@ -89,19 +80,10 @@ func MakeOIDCRole(ctx context.Context, gvk schema.GroupVersionKind, objectMeta m // So that ApiServerSource's service account have access to create the JWT token for it's OIDC service account and the target audience // Note: it is in the source.Spec, NOT in source.Auth func MakeOIDCRoleBinding(ctx context.Context, gvk schema.GroupVersionKind, objectMeta metav1.ObjectMeta, saName string) (*rbacv1.RoleBinding, error) { - logger := logging.FromContext(ctx) - logger.Errorf("haha: Initializing") - roleName := fmt.Sprintf("create-oidc-token") roleBindingName := fmt.Sprintf("create-oidc-token") - logger.Errorf("haha: going to get role binding for %s", objectMeta.Name) - logger.Errorf("haha: role name %s", roleName) - logger.Errorf("haha: role binding name %s", roleBindingName) - - logger.Errorf("haha: creating role binding") - - roleBinding := &rbacv1.RoleBinding{ + return &rbacv1.RoleBinding{ ObjectMeta: metav1.ObjectMeta{ Name: roleBindingName, Namespace: objectMeta.GetNamespace(), @@ -112,8 +94,7 @@ func MakeOIDCRoleBinding(ctx context.Context, gvk schema.GroupVersionKind, objec RoleRef: rbacv1.RoleRef{ APIGroup: "rbac.authorization.k8s.io", Kind: "Role", - //objectMeta.Name + roleName - Name: fmt.Sprintf(roleName), + Name: fmt.Sprintf(roleName), }, Subjects: []rbacv1.Subject{ { @@ -123,12 +104,7 @@ func MakeOIDCRoleBinding(ctx context.Context, gvk schema.GroupVersionKind, objec Name: saName, }, }, - } - - logger.Errorf("haha: role binding object created") - logger.Errorf("haha: role binding object %s", roleBinding) - - return roleBinding, nil + }, nil } @@ -201,7 +177,6 @@ func MakeReceiveAdapter(args *ReceiveAdapterArgs) (*appsv1.Deployment, error) { } func makeEnv(args *ReceiveAdapterArgs) ([]corev1.EnvVar, error) { - fmt.Printf("haha geting started make Env") cfg := &apiserver.Config{ Namespaces: args.Namespaces, Resources: make([]apiserver.ResourceWatch, 0, len(args.Source.Spec.Resources)), @@ -264,10 +239,7 @@ func makeEnv(args *ReceiveAdapterArgs) ([]corev1.EnvVar, error) { }) } - fmt.Printf("haha receive_adapter: trying to add the k_audience env var\n") - fmt.Printf("haha receive_adapter: args.Audience is %v\n", args.Audience) if args.Audience != nil { - fmt.Printf("haha receive_adapter: adding the k_audience env var\n") envs = append(envs, corev1.EnvVar{ Name: "K_AUDIENCE", Value: *args.Audience, @@ -275,15 +247,11 @@ func makeEnv(args *ReceiveAdapterArgs) ([]corev1.EnvVar, error) { } if args.Source.Status.Auth != nil { - //, { - //Name: "K_OIDC_SERVICE_ACCOUNT", - // Value: *args.Source.Status.Auth.ServiceAccountName, - //}, envs = append(envs, corev1.EnvVar{ Name: "K_OIDC_SERVICE_ACCOUNT", Value: *args.Source.Status.Auth.ServiceAccountName, }) - } + } envs = append(envs, args.Configs.ToEnvVars()...) From 08780d4e430704df9cf47fcb02e40f92080397ae Mon Sep 17 00:00:00 2001 From: Leo Li Date: Tue, 5 Dec 2023 01:08:46 -0500 Subject: [PATCH 17/62] Go imports Signed-off-by: Leo Li --- pkg/adapter/v2/cloudevents.go | 5 +++-- pkg/adapter/v2/config.go | 3 ++- pkg/adapter/v2/main.go | 3 ++- pkg/auth/serviceaccount.go | 3 ++- pkg/reconciler/apiserversource/resources/receive_adapter.go | 1 + test/auth/features/oidc/apiserversource.go | 1 + 6 files changed, 11 insertions(+), 5 deletions(-) diff --git a/pkg/adapter/v2/cloudevents.go b/pkg/adapter/v2/cloudevents.go index a61f4d390f0..96ac99a8c64 100644 --- a/pkg/adapter/v2/cloudevents.go +++ b/pkg/adapter/v2/cloudevents.go @@ -21,12 +21,13 @@ import ( "errors" "fmt" - "k8s.io/apimachinery/pkg/types" - "knative.dev/eventing/pkg/auth" nethttp "net/http" "net/url" "time" + "k8s.io/apimachinery/pkg/types" + "knative.dev/eventing/pkg/auth" + cloudevents "github.com/cloudevents/sdk-go/v2" ceclient "github.com/cloudevents/sdk-go/v2/client" "github.com/cloudevents/sdk-go/v2/event" diff --git a/pkg/adapter/v2/config.go b/pkg/adapter/v2/config.go index 2302e420b5c..718d4de8b6a 100644 --- a/pkg/adapter/v2/config.go +++ b/pkg/adapter/v2/config.go @@ -18,12 +18,13 @@ package adapter import ( "encoding/json" "fmt" - "k8s.io/apimachinery/pkg/types" "os" "strconv" "strings" "time" + "k8s.io/apimachinery/pkg/types" + "go.uber.org/zap" duckv1 "knative.dev/pkg/apis/duck/v1" diff --git a/pkg/adapter/v2/main.go b/pkg/adapter/v2/main.go index 70b12719250..475afb447c9 100644 --- a/pkg/adapter/v2/main.go +++ b/pkg/adapter/v2/main.go @@ -20,13 +20,14 @@ import ( "context" "flag" "fmt" - "knative.dev/eventing/pkg/auth" "log" "net/http" "strconv" "sync" "time" + "knative.dev/eventing/pkg/auth" + cloudevents "github.com/cloudevents/sdk-go/v2" "github.com/kelseyhightower/envconfig" "go.uber.org/zap" diff --git a/pkg/auth/serviceaccount.go b/pkg/auth/serviceaccount.go index 650c843269c..fe308d64247 100644 --- a/pkg/auth/serviceaccount.go +++ b/pkg/auth/serviceaccount.go @@ -19,10 +19,11 @@ package auth import ( "context" "fmt" + "strings" + "knative.dev/eventing/pkg/apis/feature" duckv1 "knative.dev/pkg/apis/duck/v1" pkgreconciler "knative.dev/pkg/reconciler" - "strings" "go.uber.org/zap" v1 "k8s.io/api/core/v1" diff --git a/pkg/reconciler/apiserversource/resources/receive_adapter.go b/pkg/reconciler/apiserversource/resources/receive_adapter.go index e3a9d2fa910..0185329f86c 100644 --- a/pkg/reconciler/apiserversource/resources/receive_adapter.go +++ b/pkg/reconciler/apiserversource/resources/receive_adapter.go @@ -20,6 +20,7 @@ import ( "context" "encoding/json" "fmt" + appsv1 "k8s.io/api/apps/v1" corev1 "k8s.io/api/core/v1" rbacv1 "k8s.io/api/rbac/v1" diff --git a/test/auth/features/oidc/apiserversource.go b/test/auth/features/oidc/apiserversource.go index 20e564d2e49..0cf727a552f 100644 --- a/test/auth/features/oidc/apiserversource.go +++ b/test/auth/features/oidc/apiserversource.go @@ -18,6 +18,7 @@ package oidc import ( "context" + "github.com/cloudevents/sdk-go/v2/test" rbacv1 "k8s.io/api/rbac/v1" v1 "knative.dev/eventing/pkg/apis/sources/v1" From 72735a358a5cf936924951dab3fa5a494e44f9a3 Mon Sep 17 00:00:00 2001 From: Leo Li Date: Tue, 5 Dec 2023 01:21:30 -0500 Subject: [PATCH 18/62] revert the wrong format change during the merging Signed-off-by: Leo Li --- SECURITY.md | 6 +- .../roles/dispatcher-clusterrole.yaml | 8 +- pkg/adapter/apiserver/delegate.go | 26 ---- pkg/kncloudevents/event_dispatcher.go | 1 - .../apiserversource/resources/role_binding.go | 46 ------ .../resources/subscription/subscription.yaml | 138 +++++++++--------- test/rekt/resources/trigger/trigger.yaml | 130 ++++++++--------- 7 files changed, 140 insertions(+), 215 deletions(-) delete mode 100644 pkg/reconciler/apiserversource/resources/role_binding.go diff --git a/SECURITY.md b/SECURITY.md index 87659b4c942..52ec3c9f24f 100644 --- a/SECURITY.md +++ b/SECURITY.md @@ -1,9 +1,7 @@ # Knative Security Policy -We're extremely grateful for security researchers and users that report vulnerabilities to the Knative Open Source -Community. All reports are thoroughly investigated by a set of community volunteers. +We're extremely grateful for security researchers and users that report vulnerabilities to the Knative Open Source Community. All reports are thoroughly investigated by a set of community volunteers. -To make a report, please email the private security@knative.team list with the security details and the details expected -for all Knative bug reports. +To make a report, please email the private security@knative.team list with the security details and the details expected for all Knative bug reports. See [Knative Security and Disclosure Information](https://knative.dev/docs/reference/security/) for more details. diff --git a/config/channels/in-memory-channel/roles/dispatcher-clusterrole.yaml b/config/channels/in-memory-channel/roles/dispatcher-clusterrole.yaml index 245dea4a1cb..549bc507f43 100644 --- a/config/channels/in-memory-channel/roles/dispatcher-clusterrole.yaml +++ b/config/channels/in-memory-channel/roles/dispatcher-clusterrole.yaml @@ -43,16 +43,16 @@ rules: verbs: - create - patch - # Create OIDC tokens +# Create OIDC tokens - apiGroups: - "" resources: - "serviceaccounts/token" verbs: - create - # Updates the finalizer so we can remove our handlers when channel is deleted - # Patches the status.subscribers to reflect when the subscription dataplane has been - # configured. +# Updates the finalizer so we can remove our handlers when channel is deleted +# Patches the status.subscribers to reflect when the subscription dataplane has been +# configured. - apiGroups: - messaging.knative.dev resources: diff --git a/pkg/adapter/apiserver/delegate.go b/pkg/adapter/apiserver/delegate.go index d88569dc020..ab0d4b63059 100644 --- a/pkg/adapter/apiserver/delegate.go +++ b/pkg/adapter/apiserver/delegate.go @@ -75,32 +75,6 @@ func (a *resourceDelegate) sendCloudEvent(ctx context.Context, event cloudevents subject := event.Context.GetSubject() a.logger.Info("sending cloudevent id: %s, source: %s, subject: %s", event.ID(), source, subject) - // Decide whether to request the JWT token or not - // Condition: if the sink has audience or not - // ?? Question: where can we get the sink audience? As we don't specify the destination in the cloudevent - - // If the sink has audience, then we need to request the JWT token - // In order to request the JWT token, we need to get the service account name and namespace from the source - // And also need to pass in OIDC token provider - // ?? Question again: where can we get the sink audience? And how to pass in OIDC token provider? - - // If the sink doesn't have audience, then we don't need to request the JWT token - - // If the sink has audience, and we have the JWT token, then we need to add the JWT token to the cloudevent - // Easy to do this, just add the JWT token as the bearer auth header to the cloudevent header - - // Discovery: - // ReceiveAdapter -> ResourceDelegate -> MakeAddEvent -> MakeEvent -> MakeCloudEvent -> SendCloudEvent - // Receive adapter is the entry point of the adapter, it receives the k8s api event - // ResourceDelegate is the cache.Store, it receives the k8s api event from the receive adapter - - //ApiServerSource will listen to the k8s api event, and then send the cloudevent to the sink when the k8s api event is created, updated or deleted - - // Prepare the headers - //headers := http.HeaderFrom(ctx) - //jwt := auth.GetJWT(ctx) - //headers.Set("Authentication", fmt.Print("Bearer %s", jwt)) - if result := a.ce.Send(ctx, event); !cloudevents.IsACK(result) { a.logger.Errorw("failed to send cloudevent", zap.Error(result), zap.String("source", source), zap.String("subject", subject), zap.String("id", event.ID())) diff --git a/pkg/kncloudevents/event_dispatcher.go b/pkg/kncloudevents/event_dispatcher.go index 86fb4eaf496..c675effeb24 100644 --- a/pkg/kncloudevents/event_dispatcher.go +++ b/pkg/kncloudevents/event_dispatcher.go @@ -343,7 +343,6 @@ func (d *Dispatcher) createRequest(ctx context.Context, message binding.Message, request.Header[key] = val } - // saw something interesting here, it is similar to what we want to do in this PR if oidcServiceAccount != nil { if target.Audience != nil && *target.Audience != "" { jwt, err := d.oidcTokenProvider.GetJWT(*oidcServiceAccount, *target.Audience) diff --git a/pkg/reconciler/apiserversource/resources/role_binding.go b/pkg/reconciler/apiserversource/resources/role_binding.go deleted file mode 100644 index 032d6b53a57..00000000000 --- a/pkg/reconciler/apiserversource/resources/role_binding.go +++ /dev/null @@ -1,46 +0,0 @@ -/* -Copyright 2020 The Knative Authors - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -package resources - -import ( - corev1 "k8s.io/api/core/v1" - rbacv1 "k8s.io/api/rbac/v1" - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" -) - -// MakeRoleBinding creates a RoleBinding object for the Apiserversource -// service account 'sa' in the Namespace 'ns'. -func MakeRoleBinding(ns, name string, sa *corev1.ServiceAccount, roleName string) *rbacv1.RoleBinding { - return &rbacv1.RoleBinding{ - ObjectMeta: metav1.ObjectMeta{ - Name: name, - Namespace: ns, - }, - RoleRef: rbacv1.RoleRef{ - APIGroup: "rbac.authorization.k8s.io", - Kind: "ClusterRole", - Name: roleName, - }, - Subjects: []rbacv1.Subject{ - { - Kind: "ServiceAccount", - Namespace: sa.Namespace, - Name: sa.Name, - }, - }, - } -} diff --git a/test/rekt/resources/subscription/subscription.yaml b/test/rekt/resources/subscription/subscription.yaml index edecba66541..7260a22be75 100644 --- a/test/rekt/resources/subscription/subscription.yaml +++ b/test/rekt/resources/subscription/subscription.yaml @@ -15,90 +15,90 @@ apiVersion: messaging.knative.dev/v1 kind: Subscription metadata: - name: { { .name } } - namespace: { { .namespace } } + name: {{ .name }} + namespace: {{ .namespace }} spec: - { { if .channel } } + {{ if .channel }} channel: - kind: { { .channel.kind } } - name: { { .channel.name } } - apiVersion: { { .channel.apiVersion } } - { { end } } + kind: {{ .channel.kind }} + name: {{ .channel.name }} + apiVersion: {{ .channel.apiVersion }} + {{ end }} {{if .subscriber }} subscriber: - { { if .subscriber.ref } } + {{ if .subscriber.ref }} ref: - kind: { { .subscriber.ref.kind } } - { { if .subscriber.ref.namespace } } - namespace: { { .subscriber.ref.namespace } } - { { else } } - namespace: { { .namespace } } - { { end } } - name: { { .subscriber.ref.name } } - apiVersion: { { .subscriber.ref.apiVersion } } - { { end } } - { { if .subscriber.uri } } - uri: { { .subscriber.uri } } - { { end } } - { { if .subscriber.CACerts } } + kind: {{ .subscriber.ref.kind }} + {{ if .subscriber.ref.namespace }} + namespace: {{ .subscriber.ref.namespace }} + {{ else }} + namespace: {{ .namespace }} + {{ end }} + name: {{ .subscriber.ref.name }} + apiVersion: {{ .subscriber.ref.apiVersion }} + {{ end }} + {{ if .subscriber.uri }} + uri: {{ .subscriber.uri }} + {{ end }} + {{ if .subscriber.CACerts }} CACerts: |- {{ .subscriber.CACerts }} - { { end } } - { { if .subscriber.audience } } - audience: { { .subscriber.audience } } - { { end } } - { { end } } + {{ end }} + {{ if .subscriber.audience }} + audience: {{ .subscriber.audience }} + {{ end }} + {{ end }} {{if .reply }} reply: - { { if .reply.ref } } + {{ if .reply.ref }} ref: - kind: { { .reply.ref.kind } } - { { if .reply.ref.namespace } } - namespace: { { .reply.ref.namespace } } - { { else } } - namespace: { { .namespace } } - { { end } } - name: { { .reply.ref.name } } - apiVersion: { { .reply.ref.apiVersion } } - { { end } } - { { if .reply.uri } } - uri: { { .reply.uri } } - { { end } } - { { if .reply.CACerts } } + kind: {{ .reply.ref.kind }} + {{ if .reply.ref.namespace }} + namespace: {{ .reply.ref.namespace }} + {{ else }} + namespace: {{ .namespace }} + {{ end }} + name: {{ .reply.ref.name }} + apiVersion: {{ .reply.ref.apiVersion }} + {{ end }} + {{ if .reply.uri }} + uri: {{ .reply.uri }} + {{ end }} + {{ if .reply.CACerts }} CACerts: |- {{ .reply.CACerts }} - { { end } } - { { end } } - { { if .delivery } } + {{ end }} + {{ end }} + {{ if .delivery }} delivery: - { { if .delivery.deadLetterSink } } + {{ if .delivery.deadLetterSink }} deadLetterSink: - { { if .delivery.deadLetterSink.ref } } + {{ if .delivery.deadLetterSink.ref }} ref: - kind: { { .delivery.deadLetterSink.ref.kind } } - { { if .delivery.deadLetterSink.ref.namespace } } - namespace: { { .delivery.deadLetterSink.ref.namespace } } - { { else } } - namespace: { { .namespace } } - { { end } } - name: { { .delivery.deadLetterSink.ref.name } } - apiVersion: { { .delivery.deadLetterSink.ref.apiVersion } } - { { end } } - { { if .delivery.deadLetterSink.uri } } - uri: { { .delivery.deadLetterSink.uri } } - { { end } } - { { if .delivery.deadLetterSink.CACerts } } + kind: {{ .delivery.deadLetterSink.ref.kind }} + {{ if .delivery.deadLetterSink.ref.namespace }} + namespace: {{ .delivery.deadLetterSink.ref.namespace }} + {{ else }} + namespace: {{ .namespace }} + {{ end }} + name: {{ .delivery.deadLetterSink.ref.name }} + apiVersion: {{ .delivery.deadLetterSink.ref.apiVersion }} + {{ end }} + {{ if .delivery.deadLetterSink.uri }} + uri: {{ .delivery.deadLetterSink.uri }} + {{ end }} + {{ if .delivery.deadLetterSink.CACerts }} CACerts: |- {{ .delivery.deadLetterSink.CACerts }} - { { end } } - { { end } } - { { if .delivery.retry } } - retry: { { .delivery.retry } } - { { end } } - { { if .delivery.backoffPolicy } } - backoffPolicy: { { .delivery.backoffPolicy } } - { { end } } - { { if .delivery.backoffDelay } } + {{ end }} + {{ end }} + {{ if .delivery.retry }} + retry: {{ .delivery.retry}} + {{ end }} + {{ if .delivery.backoffPolicy }} + backoffPolicy: {{ .delivery.backoffPolicy}} + {{ end }} + {{ if .delivery.backoffDelay }} backoffDelay: "{{ .delivery.backoffDelay}}" - { { end } } - { { end } } + {{ end }} + {{ end }} diff --git a/test/rekt/resources/trigger/trigger.yaml b/test/rekt/resources/trigger/trigger.yaml index 79d00c24316..2a22ed3d893 100644 --- a/test/rekt/resources/trigger/trigger.yaml +++ b/test/rekt/resources/trigger/trigger.yaml @@ -15,74 +15,74 @@ apiVersion: eventing.knative.dev/v1 kind: Trigger metadata: - name: { { .name } } - namespace: { { .namespace } } - { { if .annotations } } + name: {{ .name }} + namespace: {{ .namespace }} + {{ if .annotations }} annotations: - { { range $key, $value := .annotations } } - { { $key } }: { { $value } } - { { end } } - { { end } } + {{ range $key, $value := .annotations }} + {{ $key }}: {{ $value }} + {{ end }} + {{ end }} spec: - { { if .brokerName } } - broker: { { .brokerName } } - { { end } } - { { if .filter } } + {{ if .brokerName }} + broker: {{ .brokerName }} + {{ end }} + {{ if .filter }} filter: attributes: - { { range $key, $value := .filter.attributes } } - { { $key } }: "{{ $value }}" - { { end } } - { { end } } - { { if .filters } } + {{ range $key, $value := .filter.attributes }} + {{ $key }}: "{{ $value }}" + {{ end }} + {{ end }} + {{ if .filters }} filters: - { { .filters } } - { { end } } - { { if .subscriber } } -subscriber: - { { if .subscriber.ref } } - ref: - kind: { { .subscriber.ref.kind } } - namespace: { { .namespace } } - name: { { .subscriber.ref.name } } - apiVersion: { { .subscriber.ref.apiVersion } } - { { end } } - { { if .subscriber.uri } } - uri: { { .subscriber.uri } } - { { end } } - { { if .subscriber.CACerts } } - CACerts: |- - {{ .subscriber.CACerts }} - { { end } } - { { if .subscriber.audience } } -audience: { { .subscriber.audience } } - { { end } } - { { end } } - { { if .delivery } } -delivery: - { { if .delivery.timeout } } - timeout: { { .delivery.timeout } } - { { end } } - { { if .delivery.deadLetterSink } } - deadLetterSink: - { { if .delivery.deadLetterSink.ref } } +{{ .filters }} + {{ end }} + {{ if .subscriber }} + subscriber: + {{ if .subscriber.ref }} ref: - kind: { { .delivery.deadLetterSink.ref.kind } } - namespace: { { .namespace } } - name: { { .delivery.deadLetterSink.ref.name } } - apiVersion: { { .delivery.deadLetterSink.ref.apiVersion } } - { { end } } - { { if .delivery.deadLetterSink.uri } } - uri: { { .delivery.deadLetterSink.uri } } - { { end } } - { { end } } - { { if .delivery.retry } } - retry: { { .delivery.retry } } - { { end } } - { { if .delivery.backoffPolicy } } - backoffPolicy: { { .delivery.backoffPolicy } } - { { end } } - { { if .delivery.backoffDelay } } - backoffDelay: "{{ .delivery.backoffDelay}}" - { { end } } - { { end } } + kind: {{ .subscriber.ref.kind }} + namespace: {{ .namespace }} + name: {{ .subscriber.ref.name }} + apiVersion: {{ .subscriber.ref.apiVersion }} + {{ end }} + {{ if .subscriber.uri }} + uri: {{ .subscriber.uri }} + {{ end }} + {{ if .subscriber.CACerts }} + CACerts: |- + {{ .subscriber.CACerts }} + {{ end }} + {{ if .subscriber.audience }} + audience: {{ .subscriber.audience }} + {{ end }} + {{ end }} + {{ if .delivery }} + delivery: + {{ if .delivery.timeout }} + timeout: {{ .delivery.timeout }} + {{ end }} + {{ if .delivery.deadLetterSink }} + deadLetterSink: + {{ if .delivery.deadLetterSink.ref }} + ref: + kind: {{ .delivery.deadLetterSink.ref.kind }} + namespace: {{ .namespace }} + name: {{ .delivery.deadLetterSink.ref.name }} + apiVersion: {{ .delivery.deadLetterSink.ref.apiVersion }} + {{ end }} + {{ if .delivery.deadLetterSink.uri }} + uri: {{ .delivery.deadLetterSink.uri }} + {{ end }} + {{ end }} + {{ if .delivery.retry }} + retry: {{ .delivery.retry}} + {{ end }} + {{ if .delivery.backoffPolicy }} + backoffPolicy: {{ .delivery.backoffPolicy}} + {{ end }} + {{ if .delivery.backoffDelay }} + backoffDelay: "{{ .delivery.backoffDelay}}" + {{ end }} + {{ end }} From 8bfb205f865d5c61bba6dc040fb46bb2cc320569 Mon Sep 17 00:00:00 2001 From: Leo Li Date: Tue, 5 Dec 2023 01:29:16 -0500 Subject: [PATCH 19/62] Self sanity check before requesting review Signed-off-by: Leo Li --- pkg/adapter/v2/cloudevents.go | 2 -- pkg/adapter/v2/config.go | 20 ------------------- .../apiserversource/apiserversource.go | 4 ---- test/auth/features/oidc/apiserversource.go | 5 ----- 4 files changed, 31 deletions(-) diff --git a/pkg/adapter/v2/cloudevents.go b/pkg/adapter/v2/cloudevents.go index 96ac99a8c64..373b717e06d 100644 --- a/pkg/adapter/v2/cloudevents.go +++ b/pkg/adapter/v2/cloudevents.go @@ -139,8 +139,6 @@ func NewClient(cfg ClientConfig) (Client, error) { pOpts := make([]http.Option, 0) - //OIDCTokenProvider := auth.NewOIDCTokenProvider(cfg.Context) - ceOverrides := cfg.CeOverrides if cfg.Env != nil { if target := cfg.Env.GetSink(); len(target) > 0 { diff --git a/pkg/adapter/v2/config.go b/pkg/adapter/v2/config.go index 718d4de8b6a..94f8b08f562 100644 --- a/pkg/adapter/v2/config.go +++ b/pkg/adapter/v2/config.go @@ -17,10 +17,8 @@ package adapter import ( "encoding/json" - "fmt" "os" "strconv" - "strings" "time" "k8s.io/apimachinery/pkg/types" @@ -167,24 +165,6 @@ func (e *EnvConfig) GetMetricsConfig() (*metrics.ExporterOptions, error) { return metricsConfig, err } -func extractSinkName(url string) (string, error) { - // Check if URL contains http://, remove it for easier processing - if strings.HasPrefix(url, "http://") { - url = strings.TrimPrefix(url, "http://") - } - - // Split the URL by '.' to isolate the components - parts := strings.Split(url, ".") - if len(parts) == 0 { - return "", fmt.Errorf("invalid URL format") - } - - // The first part of the URL is expected to be the sink name - sinkName := parts[0] - - return sinkName, nil -} - func (e *EnvConfig) GetLogger() *zap.SugaredLogger { if e.logger == nil { loggingConfig, err := logging.JSONToConfig(e.LoggingConfigJson) diff --git a/pkg/reconciler/apiserversource/apiserversource.go b/pkg/reconciler/apiserversource/apiserversource.go index 479386388d4..7679fae7bb9 100644 --- a/pkg/reconciler/apiserversource/apiserversource.go +++ b/pkg/reconciler/apiserversource/apiserversource.go @@ -215,8 +215,6 @@ func (r *Reconciler) createReceiveAdapter(ctx context.Context, src *v1.ApiServer // return nil, err // } - // trying to figure out why audience is empty - adapterArgs := resources.ReceiveAdapterArgs{ Image: r.receiveAdapterImage, Source: src, @@ -365,8 +363,6 @@ func (r *Reconciler) createCloudEventAttributes(src *v1.ApiServerSource) ([]duck return ceAttributes, nil } -// TODO: adding the rolebinding function to the resource folder and the role to the auth folder - // createOIDCRole: this function will call resources package to get the role object // and then pass to kubeclient to make the actual OIDC role func createOIDCRole(ctx context.Context, kubeclient kubernetes.Interface, gvk schema.GroupVersionKind, objectMeta metav1.ObjectMeta) error { diff --git a/test/auth/features/oidc/apiserversource.go b/test/auth/features/oidc/apiserversource.go index 0cf727a552f..9cff2e398c1 100644 --- a/test/auth/features/oidc/apiserversource.go +++ b/test/auth/features/oidc/apiserversource.go @@ -44,9 +44,6 @@ func ApiserversourceSendEventWithJWT() *feature.Feature { f := feature.NewFeatureNamed("Send events to sink") - //f.Prerequisite("should not run when Istio is enabled", featureflags.IstioDisabled()) - //f.Prerequisite("transport encryption is strict", featureflags.TransportEncryptionStrict()) - f.Setup("deploy receiver", eventshub.Install(sink, eventshub.StartReceiver, eventshub.OIDCReceiverAudience(audience))) @@ -85,8 +82,6 @@ func ApiserversourceSendEventWithJWT() *feature.Feature { MatchEvent(test.HasType("dev.knative.apiserver.resource.update")). AtLeast(1), ) - //Must("Set sinkURI to HTTPS endpoint", source.ExpectHTTPSSink(apiserversource.Gvr(), src)). - //Must("Set sinkCACerts to non empty CA certs", source.ExpectCACerts(apiserversource.Gvr(), src)) return f } From d125209146b781b8ae528daf7c822c9b8c0e95ab Mon Sep 17 00:00:00 2001 From: Leo Li Date: Tue, 5 Dec 2023 02:10:13 -0500 Subject: [PATCH 20/62] Fix the failed unit test Signed-off-by: Leo Li --- pkg/adapter/v2/cloudevents.go | 25 +++++++++++-------- pkg/adapter/v2/config.go | 6 ++--- pkg/auth/token_provider.go | 2 -- .../apiserversource/apiserversource.go | 4 +-- .../resources/receive_adapter.go | 13 +++++----- 5 files changed, 26 insertions(+), 24 deletions(-) diff --git a/pkg/adapter/v2/cloudevents.go b/pkg/adapter/v2/cloudevents.go index 373b717e06d..32796b2680e 100644 --- a/pkg/adapter/v2/cloudevents.go +++ b/pkg/adapter/v2/cloudevents.go @@ -197,16 +197,21 @@ func NewClient(cfg ClientConfig) (Client, error) { return nil, err } - return &client{ + client := &client{ ceClient: ceClient, closeIdler: transport.Base.(*nethttp.Transport), ceOverrides: ceOverrides, reporter: cfg.Reporter, crStatusEventClient: cfg.CrStatusEventClient, - audience: cfg.Env.GetAudience(), - serviceAccountName: cfg.Env.GetServiceAccountName(), - oidcTokenProvider: cfg.TokenProvider, - }, nil + } + + if cfg.Env != nil { + client.audience = cfg.Env.GetAudience() + client.serviceAccountName = cfg.Env.GetServiceAccountName() + client.oidcTokenProvider = cfg.TokenProvider + } + + return client, nil } func setTimeOut(duration time.Duration) http.Option { @@ -230,7 +235,7 @@ type client struct { closeIdler closeIdler oidcTokenProvider *auth.OIDCTokenProvider - audience string + audience *string serviceAccountName *types.NamespacedName } @@ -245,9 +250,9 @@ func (c *client) Send(ctx context.Context, out event.Event) protocol.Result { c.applyOverrides(&out) // If the sink has audience and the OIDC service account, then we need to request the JWT token - if c.audience != "" && c.serviceAccountName != nil { + if c.audience != nil && c.serviceAccountName != nil { // Request the JWT token for the given service account - jwt, err := c.oidcTokenProvider.GetJWT(*c.serviceAccountName, c.audience) + jwt, err := c.oidcTokenProvider.GetJWT(*c.serviceAccountName, *c.audience) if err != nil { return protocol.NewResult("%w", err) } @@ -268,9 +273,9 @@ func (c *client) Request(ctx context.Context, out event.Event) (*event.Event, pr c.applyOverrides(&out) // If the sink has audience and the OIDC service account, then we need to request the JWT token - if c.audience != "" && c.serviceAccountName != nil { + if c.audience != nil && c.serviceAccountName != nil { // Request the JWT token for the given service account - jwt, err := c.oidcTokenProvider.GetJWT(*c.serviceAccountName, c.audience) + jwt, err := c.oidcTokenProvider.GetJWT(*c.serviceAccountName, *c.audience) if err != nil { return nil, protocol.NewResult("%w", err) } diff --git a/pkg/adapter/v2/config.go b/pkg/adapter/v2/config.go index 94f8b08f562..0de7e12047b 100644 --- a/pkg/adapter/v2/config.go +++ b/pkg/adapter/v2/config.go @@ -70,7 +70,7 @@ type EnvConfig struct { Sink string `envconfig:"K_SINK"` // Audience is the audience of the target sink. - Audience string `envconfig:"K_AUDIENCE"` + Audience *string `envconfig:"K_AUDIENCE"` // Service Account Name is the name of the service account to use for the adapter. ServiceAccountName *string `envconfig:"K_OIDC_SERVICE_ACCOUNT"` @@ -123,7 +123,7 @@ type EnvConfigAccessor interface { GetCACerts() *string // Get the audience of the target sink. - GetAudience() string + GetAudience() *string GetServiceAccountName() *types.NamespacedName @@ -202,7 +202,7 @@ func (e *EnvConfig) GetCACerts() *string { return e.CACerts } -func (e *EnvConfig) GetAudience() string { +func (e *EnvConfig) GetAudience() *string { return e.Audience } diff --git a/pkg/auth/token_provider.go b/pkg/auth/token_provider.go index 2d5423ecc41..6fb115f9d4e 100644 --- a/pkg/auth/token_provider.go +++ b/pkg/auth/token_provider.go @@ -79,8 +79,6 @@ func (c *OIDCTokenProvider) GetNewJWT(serviceAccount types.NamespacedName, audie CreateToken(context.TODO(), serviceAccount.Name, &tokenRequest, metav1.CreateOptions{}) if err != nil { - fmt.Sprintf("could not request a token for %s: %w", serviceAccount, err) - return "", fmt.Errorf("could not request a token for %s: %w", serviceAccount, err) } diff --git a/pkg/reconciler/apiserversource/apiserversource.go b/pkg/reconciler/apiserversource/apiserversource.go index 7679fae7bb9..6d619f0fa08 100644 --- a/pkg/reconciler/apiserversource/apiserversource.go +++ b/pkg/reconciler/apiserversource/apiserversource.go @@ -372,7 +372,7 @@ func createOIDCRole(ctx context.Context, kubeclient kubernetes.Interface, gvk sc _, err := kubeclient.RbacV1().Roles(objectMeta.Namespace).Get(ctx, roleName, metav1.GetOptions{}) if apierrs.IsNotFound(err) { - role, err := resources.MakeOIDCRole(ctx, gvk, objectMeta) + role, err := resources.MakeOIDCRole(gvk, objectMeta) // If the role does not exist, we will call kubeclient to create it _, err = kubeclient.RbacV1().Roles(objectMeta.Namespace).Create(ctx, role, metav1.CreateOptions{}) if err != nil { @@ -394,7 +394,7 @@ func createOIDCRoleBinding(ctx context.Context, kubeclient kubernetes.Interface, _, err := kubeclient.RbacV1().RoleBindings(objectMeta.Namespace).Get(ctx, roleBindingName, metav1.GetOptions{}) if apierrs.IsNotFound(err) { - roleBinding, err := resources.MakeOIDCRoleBinding(ctx, gvk, objectMeta, saName) + roleBinding, err := resources.MakeOIDCRoleBinding(gvk, objectMeta, saName) // If the role does not exist, we will call kubeclient to create it _, err = kubeclient.RbacV1().RoleBindings(objectMeta.Namespace).Create(ctx, roleBinding, metav1.CreateOptions{}) if err != nil { diff --git a/pkg/reconciler/apiserversource/resources/receive_adapter.go b/pkg/reconciler/apiserversource/resources/receive_adapter.go index 0185329f86c..974c6e4cf64 100644 --- a/pkg/reconciler/apiserversource/resources/receive_adapter.go +++ b/pkg/reconciler/apiserversource/resources/receive_adapter.go @@ -17,7 +17,6 @@ limitations under the License. package resources import ( - "context" "encoding/json" "fmt" @@ -54,8 +53,8 @@ type ReceiveAdapterArgs struct { } // MakeOIDCRole will return the role object config for generating the JWT token -func MakeOIDCRole(ctx context.Context, gvk schema.GroupVersionKind, objectMeta metav1.ObjectMeta) (*rbacv1.Role, error) { - roleName := fmt.Sprintf("create-oidc-token") +func MakeOIDCRole(gvk schema.GroupVersionKind, objectMeta metav1.ObjectMeta) (*rbacv1.Role, error) { + roleName := "create-oidc-token" return &rbacv1.Role{ ObjectMeta: metav1.ObjectMeta{ @@ -80,9 +79,9 @@ func MakeOIDCRole(ctx context.Context, gvk schema.GroupVersionKind, objectMeta m // MakeOIDCRoleBinding will return the rolebinding object for generating the JWT token // So that ApiServerSource's service account have access to create the JWT token for it's OIDC service account and the target audience // Note: it is in the source.Spec, NOT in source.Auth -func MakeOIDCRoleBinding(ctx context.Context, gvk schema.GroupVersionKind, objectMeta metav1.ObjectMeta, saName string) (*rbacv1.RoleBinding, error) { - roleName := fmt.Sprintf("create-oidc-token") - roleBindingName := fmt.Sprintf("create-oidc-token") +func MakeOIDCRoleBinding(gvk schema.GroupVersionKind, objectMeta metav1.ObjectMeta, saName string) (*rbacv1.RoleBinding, error) { + roleName := "create-oidc-token" + roleBindingName := "create-oidc-token" return &rbacv1.RoleBinding{ ObjectMeta: metav1.ObjectMeta{ @@ -95,7 +94,7 @@ func MakeOIDCRoleBinding(ctx context.Context, gvk schema.GroupVersionKind, objec RoleRef: rbacv1.RoleRef{ APIGroup: "rbac.authorization.k8s.io", Kind: "Role", - Name: fmt.Sprintf(roleName), + Name: roleName, }, Subjects: []rbacv1.Subject{ { From 55e5c3020058b1e3cce0c3ff815592f4e4d48699 Mon Sep 17 00:00:00 2001 From: Leo Li Date: Tue, 5 Dec 2023 13:19:39 -0500 Subject: [PATCH 21/62] Fix the review comments Signed-off-by: Leo Li --- pkg/adapter/apiserver/delegate.go | 4 +- pkg/adapter/v2/cloudevents.go | 82 +++++++++++++------ pkg/adapter/v2/config.go | 2 + .../apiserversource/apiserversource.go | 24 +++--- .../resources/receive_adapter.go | 36 ++++---- test/upgrade/prober/receiver.go | 2 +- 6 files changed, 95 insertions(+), 55 deletions(-) diff --git a/pkg/adapter/apiserver/delegate.go b/pkg/adapter/apiserver/delegate.go index ab0d4b63059..e45d87e67ae 100644 --- a/pkg/adapter/apiserver/delegate.go +++ b/pkg/adapter/apiserver/delegate.go @@ -73,13 +73,13 @@ func (a *resourceDelegate) sendCloudEvent(ctx context.Context, event cloudevents defer a.logger.Debug("Finished sending cloudevent id: ", event.ID()) source := event.Context.GetSource() subject := event.Context.GetSubject() - a.logger.Info("sending cloudevent id: %s, source: %s, subject: %s", event.ID(), source, subject) + a.logger.Debugf("sending cloudevent id: %s, source: %s, subject: %s", event.ID(), source, subject) if result := a.ce.Send(ctx, event); !cloudevents.IsACK(result) { a.logger.Errorw("failed to send cloudevent", zap.Error(result), zap.String("source", source), zap.String("subject", subject), zap.String("id", event.ID())) } else { - a.logger.Info("cloudevent sent id: %s, source: %s, subject: %s", event.ID(), source, subject) + a.logger.Debugf("cloudevent sent id: %s, source: %s, subject: %s", event.ID(), source, subject) } } diff --git a/pkg/adapter/v2/cloudevents.go b/pkg/adapter/v2/cloudevents.go index 32796b2680e..3395d480b2a 100644 --- a/pkg/adapter/v2/cloudevents.go +++ b/pkg/adapter/v2/cloudevents.go @@ -203,12 +203,12 @@ func NewClient(cfg ClientConfig) (Client, error) { ceOverrides: ceOverrides, reporter: cfg.Reporter, crStatusEventClient: cfg.CrStatusEventClient, + oidcTokenProvider: cfg.TokenProvider, } if cfg.Env != nil { client.audience = cfg.Env.GetAudience() client.serviceAccountName = cfg.Env.GetServiceAccountName() - client.oidcTokenProvider = cfg.TokenProvider } return client, nil @@ -249,18 +249,23 @@ var _ cloudevents.Client = (*client)(nil) func (c *client) Send(ctx context.Context, out event.Event) protocol.Result { c.applyOverrides(&out) - // If the sink has audience and the OIDC service account, then we need to request the JWT token - if c.audience != nil && c.serviceAccountName != nil { - // Request the JWT token for the given service account - jwt, err := c.oidcTokenProvider.GetJWT(*c.serviceAccountName, *c.audience) - if err != nil { - return protocol.NewResult("%w", err) - } - - // Appending the auth token to the outgoing request - headers := http.HeaderFrom(ctx) - headers.Set("Authorization", fmt.Sprintf("Bearer %s", jwt)) - ctx = http.WithCustomHeader(ctx, headers) + //// If the sink has audience and the OIDC service account, then we need to request the JWT token + //if c.audience != nil && c.serviceAccountName != nil { + // // Request the JWT token for the given service account + // jwt, err := c.oidcTokenProvider.GetJWT(*c.serviceAccountName, *c.audience) + // if err != nil { + // return protocol.NewResult("%w", err) + // } + // + // // Appending the auth token to the outgoing request + // headers := http.HeaderFrom(ctx) + // headers.Set("Authorization", fmt.Sprintf("Bearer %s", jwt)) + // ctx = http.WithCustomHeader(ctx, headers) + //} + + err := c.appendAuthHeader(&ctx) + if err != nil { + return err } res := c.ceClient.Send(ctx, out) @@ -272,20 +277,24 @@ func (c *client) Send(ctx context.Context, out event.Event) protocol.Result { func (c *client) Request(ctx context.Context, out event.Event) (*event.Event, protocol.Result) { c.applyOverrides(&out) - // If the sink has audience and the OIDC service account, then we need to request the JWT token - if c.audience != nil && c.serviceAccountName != nil { - // Request the JWT token for the given service account - jwt, err := c.oidcTokenProvider.GetJWT(*c.serviceAccountName, *c.audience) - if err != nil { - return nil, protocol.NewResult("%w", err) - } - - // Appending the auth token to the outgoing request - headers := http.HeaderFrom(ctx) - headers.Set("Authorization", fmt.Sprintf("Bearer %s", jwt)) - ctx = http.WithCustomHeader(ctx, headers) + //// If the sink has audience and the OIDC service account, then we need to request the JWT token + //if c.audience != nil && c.serviceAccountName != nil { + // // Request the JWT token for the given service account + // jwt, err := c.oidcTokenProvider.GetJWT(*c.serviceAccountName, *c.audience) + // if err != nil { + // return nil, protocol.NewResult("%w", err) + // } + // + // // Appending the auth token to the outgoing request + // headers := http.HeaderFrom(ctx) + // headers.Set("Authorization", fmt.Sprintf("Bearer %s", jwt)) + // ctx = http.WithCustomHeader(ctx, headers) + //} + + err := c.appendAuthHeader(&ctx) + if err != nil { + return nil, err } - resp, res := c.ceClient.Request(ctx, out) c.reportMetrics(ctx, out, res) return resp, res @@ -411,3 +420,24 @@ func tracecontextMiddleware(h nethttp.Handler) nethttp.Handler { FormatSpanName: formatSpanName, } } + +// When OIDC is enabled, appendAuthHeader will request the JWT token from the tokenProvider and append it to every request +// it has interaction with, if source's OIDC service account (source.Status.Auth.ServiceAccountName) and destination's +// audience are present. +func (c *client) appendAuthHeader(ctx *context.Context) error { + // If the sink has audience and the OIDC service account, then we need to request the JWT token + if c.audience != nil && c.serviceAccountName != nil { + // Request the JWT token for the given service account + jwt, err := c.oidcTokenProvider.GetJWT(*c.serviceAccountName, *c.audience) + if err != nil { + return protocol.NewResult("%w", err) + } + + // Appending the auth token to the outgoing request + headers := http.HeaderFrom(*ctx) + headers.Set("Authorization", fmt.Sprintf("Bearer %s", jwt)) + *ctx = http.WithCustomHeader(*ctx, headers) + } + + return nil +} diff --git a/pkg/adapter/v2/config.go b/pkg/adapter/v2/config.go index 0de7e12047b..bf20c14ece4 100644 --- a/pkg/adapter/v2/config.go +++ b/pkg/adapter/v2/config.go @@ -42,6 +42,7 @@ const ( EnvConfigResourceGroup = "K_RESOURCE_GROUP" EnvConfigSink = "K_SINK" EnvConfigAudience = "K_AUDIENCE" + EnvConfigOIDCServiceAccount = "K_OIDC_SERVICE_ACCOUNT" EnvConfigCACert = "K_CA_CERTS" EnvConfigCEOverrides = "K_CE_OVERRIDES" EnvConfigMetricsConfig = "K_METRICS_CONFIG" @@ -125,6 +126,7 @@ type EnvConfigAccessor interface { // Get the audience of the target sink. GetAudience() *string + // Get the service account name to use for the adapter. GetServiceAccountName() *types.NamespacedName // Get the namespace of the adapter. diff --git a/pkg/reconciler/apiserversource/apiserversource.go b/pkg/reconciler/apiserversource/apiserversource.go index 6d619f0fa08..1f84be8c8fa 100644 --- a/pkg/reconciler/apiserversource/apiserversource.go +++ b/pkg/reconciler/apiserversource/apiserversource.go @@ -111,7 +111,7 @@ func (r *Reconciler) ReconcileKind(ctx context.Context, source *v1.ApiServerSour if featureFlags.IsOIDCAuthentication() { // Create the role - err := createOIDCRole(ctx, r.kubeClientSet, v1.SchemeGroupVersion.WithKind("ApiServerSource"), source.ObjectMeta) + err := r.createOIDCRole(ctx, source) if err != nil { logging.FromContext(ctx).Errorw("Failed when creating the OIDC Role for ApiServerSource", zap.Error(err)) @@ -119,7 +119,7 @@ func (r *Reconciler) ReconcileKind(ctx context.Context, source *v1.ApiServerSour } // Create the rolebinding - err = createOIDCRoleBinding(ctx, r.kubeClientSet, v1.SchemeGroupVersion.WithKind("ApiServerSource"), source.ObjectMeta, source.Spec.ServiceAccountName) + err = r.createOIDCRoleBinding(ctx, source) if err != nil { logging.FromContext(ctx).Errorw("Failed when creating the OIDC RoleBinding for ApiServerSource", zap.Error(err)) return err @@ -365,18 +365,18 @@ func (r *Reconciler) createCloudEventAttributes(src *v1.ApiServerSource) ([]duck // createOIDCRole: this function will call resources package to get the role object // and then pass to kubeclient to make the actual OIDC role -func createOIDCRole(ctx context.Context, kubeclient kubernetes.Interface, gvk schema.GroupVersionKind, objectMeta metav1.ObjectMeta) error { +func (r *Reconciler) createOIDCRole(ctx context.Context, source *v1.ApiServerSource) error { roleName := "create-oidc-token" //Call kubeclient and see whether the role exist or not - _, err := kubeclient.RbacV1().Roles(objectMeta.Namespace).Get(ctx, roleName, metav1.GetOptions{}) + _, err := r.kubeClientSet.RbacV1().Roles(source.GetNamespace()).Get(ctx, roleName, metav1.GetOptions{}) if apierrs.IsNotFound(err) { - role, err := resources.MakeOIDCRole(gvk, objectMeta) + role, err := resources.MakeOIDCRole(source) // If the role does not exist, we will call kubeclient to create it - _, err = kubeclient.RbacV1().Roles(objectMeta.Namespace).Create(ctx, role, metav1.CreateOptions{}) + _, err = r.kubeClientSet.RbacV1().Roles(source.GetNamespace()).Create(ctx, role, metav1.CreateOptions{}) if err != nil { - return fmt.Errorf("could not create OIDC service account role %s/%s for %s: %w", objectMeta.Name, objectMeta.Namespace, gvk.Kind, err) + return fmt.Errorf("could not create OIDC service account role %s/%s for %s: %w", source.GetName(), source.GetNamespace(), "ApiServerSource", err) } } @@ -387,18 +387,18 @@ func createOIDCRole(ctx context.Context, kubeclient kubernetes.Interface, gvk sc // createOIDCRoleBinding: this function will call resources package to get the rolebinding object // and then pass to kubeclient to make the actual OIDC rolebinding -func createOIDCRoleBinding(ctx context.Context, kubeclient kubernetes.Interface, gvk schema.GroupVersionKind, objectMeta metav1.ObjectMeta, saName string) error { +func (r *Reconciler) createOIDCRoleBinding(ctx context.Context, source *v1.ApiServerSource) error { roleBindingName := "create-oidc-token" // Call kubeclient and see whether the roleBinding exist or not - _, err := kubeclient.RbacV1().RoleBindings(objectMeta.Namespace).Get(ctx, roleBindingName, metav1.GetOptions{}) + _, err := r.kubeClientSet.RbacV1().RoleBindings(source.GetNamespace()).Get(ctx, roleBindingName, metav1.GetOptions{}) if apierrs.IsNotFound(err) { - roleBinding, err := resources.MakeOIDCRoleBinding(gvk, objectMeta, saName) + roleBinding, err := resources.MakeOIDCRoleBinding(source) // If the role does not exist, we will call kubeclient to create it - _, err = kubeclient.RbacV1().RoleBindings(objectMeta.Namespace).Create(ctx, roleBinding, metav1.CreateOptions{}) + _, err = r.kubeClientSet.RbacV1().RoleBindings(source.GetNamespace()).Create(ctx, roleBinding, metav1.CreateOptions{}) if err != nil { - return fmt.Errorf("could not create OIDC service account rolebinding %s/%s for %s: %w", objectMeta.Name, objectMeta.Namespace, gvk.Kind, err) + return fmt.Errorf("could not create OIDC service account rolebinding %s/%s for %s: %w", source.GetName(), source.GetNamespace(), "apiserversource", err) } } diff --git a/pkg/reconciler/apiserversource/resources/receive_adapter.go b/pkg/reconciler/apiserversource/resources/receive_adapter.go index 974c6e4cf64..d74d0ea8a84 100644 --- a/pkg/reconciler/apiserversource/resources/receive_adapter.go +++ b/pkg/reconciler/apiserversource/resources/receive_adapter.go @@ -28,7 +28,6 @@ import ( "k8s.io/apimachinery/pkg/runtime/schema" "k8s.io/apimachinery/pkg/util/intstr" "knative.dev/eventing/pkg/adapter/v2" - "knative.dev/eventing/pkg/auth" "knative.dev/pkg/kmeta" "knative.dev/pkg/ptr" "knative.dev/pkg/system" @@ -53,21 +52,26 @@ type ReceiveAdapterArgs struct { } // MakeOIDCRole will return the role object config for generating the JWT token -func MakeOIDCRole(gvk schema.GroupVersionKind, objectMeta metav1.ObjectMeta) (*rbacv1.Role, error) { +func MakeOIDCRole(source *v1.ApiServerSource) (*rbacv1.Role, error) { roleName := "create-oidc-token" + if source.Status.Auth.ServiceAccountName == nil { + return nil, fmt.Errorf("Error when making OIDC Role for apiserversource, as the OIDC service account does not exist") + } + return &rbacv1.Role{ ObjectMeta: metav1.ObjectMeta{ Name: roleName, - Namespace: objectMeta.GetNamespace(), + Namespace: source.GetNamespace(), Annotations: map[string]string{ - "description": fmt.Sprintf("Role for OIDC Authentication for %s %q", gvk.GroupKind().Kind, objectMeta.Name), + "description": fmt.Sprintf("Role for OIDC Authentication for %s %q", "ApiServerSource", source.GetName()), }, }, Rules: []rbacv1.PolicyRule{ rbacv1.PolicyRule{ - APIGroups: []string{""}, - ResourceNames: []string{auth.GetOIDCServiceAccountNameForResource(gvk, objectMeta)}, + APIGroups: []string{""}, + // apiServerSource OIDC service account name, it is in the source.Status, NOT in source.Spec + ResourceNames: []string{*source.Status.Auth.ServiceAccountName}, Resources: []string{"serviceaccounts/token"}, Verbs: []string{"create"}, }, @@ -79,16 +83,20 @@ func MakeOIDCRole(gvk schema.GroupVersionKind, objectMeta metav1.ObjectMeta) (*r // MakeOIDCRoleBinding will return the rolebinding object for generating the JWT token // So that ApiServerSource's service account have access to create the JWT token for it's OIDC service account and the target audience // Note: it is in the source.Spec, NOT in source.Auth -func MakeOIDCRoleBinding(gvk schema.GroupVersionKind, objectMeta metav1.ObjectMeta, saName string) (*rbacv1.RoleBinding, error) { +func MakeOIDCRoleBinding(source *v1.ApiServerSource) (*rbacv1.RoleBinding, error) { roleName := "create-oidc-token" roleBindingName := "create-oidc-token" + if source.Spec.ServiceAccountName == "" { + return nil, fmt.Errorf("Error when making OIDC RoleBinding for apiserversource, as the Spec service account does not exist") + } + return &rbacv1.RoleBinding{ ObjectMeta: metav1.ObjectMeta{ Name: roleBindingName, - Namespace: objectMeta.GetNamespace(), + Namespace: source.GetNamespace(), Annotations: map[string]string{ - "description": fmt.Sprintf("Role Binding for OIDC Authentication for %s %q", gvk.GroupKind().Kind, objectMeta.Name), + "description": fmt.Sprintf("Role Binding for OIDC Authentication for %s %q", "ApiServerSource", source.GetName()), }, }, RoleRef: rbacv1.RoleRef{ @@ -99,9 +107,9 @@ func MakeOIDCRoleBinding(gvk schema.GroupVersionKind, objectMeta metav1.ObjectMe Subjects: []rbacv1.Subject{ { Kind: "ServiceAccount", - Namespace: objectMeta.GetNamespace(), - //Note: apiServerSource service account name, it is in the source.Spec, NOT in source.Auth - Name: saName, + Namespace: source.GetNamespace(), + //Note: apiServerSource service account name, it is in the source.Spec, NOT in source.Status.Auth + Name: source.Spec.ServiceAccountName, }, }, }, nil @@ -241,14 +249,14 @@ func makeEnv(args *ReceiveAdapterArgs) ([]corev1.EnvVar, error) { if args.Audience != nil { envs = append(envs, corev1.EnvVar{ - Name: "K_AUDIENCE", + Name: adapter.EnvConfigAudience, Value: *args.Audience, }) } if args.Source.Status.Auth != nil { envs = append(envs, corev1.EnvVar{ - Name: "K_OIDC_SERVICE_ACCOUNT", + Name: adapter.EnvConfigOIDCServiceAccount, Value: *args.Source.Status.Auth.ServiceAccountName, }) } diff --git a/test/upgrade/prober/receiver.go b/test/upgrade/prober/receiver.go index ca2dcf37c54..a706871a5c3 100644 --- a/test/upgrade/prober/receiver.go +++ b/test/upgrade/prober/receiver.go @@ -74,7 +74,7 @@ func (p *prober) deployReceiverService() { p.client.CreateServiceOrFail(service) } -func (p *prober) createReceiverDeployment() *appsv1.Deployment { +func (p *prober) iverDeployment() *appsv1.Deployment { var replicas int32 = 1 return &appsv1.Deployment{ ObjectMeta: metav1.ObjectMeta{ From a3c9ca8d12476ebf007ec98496a13ff87c0da2f2 Mon Sep 17 00:00:00 2001 From: Leo Li Date: Tue, 5 Dec 2023 13:20:01 -0500 Subject: [PATCH 22/62] Update test/auth/features/oidc/apiserversource.go MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Christoph Stäbler --- test/auth/features/oidc/apiserversource.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/auth/features/oidc/apiserversource.go b/test/auth/features/oidc/apiserversource.go index 9cff2e398c1..07c2b5f6178 100644 --- a/test/auth/features/oidc/apiserversource.go +++ b/test/auth/features/oidc/apiserversource.go @@ -47,7 +47,7 @@ func ApiserversourceSendEventWithJWT() *feature.Feature { f.Setup("deploy receiver", eventshub.Install(sink, eventshub.StartReceiver, eventshub.OIDCReceiverAudience(audience))) - // + f.Setup("Create Service Account for ApiServerSource with RBAC for v1.Event resources", setupAccountAndRoleForApiserversource(sacmName)) From a924341ca2b721f70556e71255089d25de6f8c20 Mon Sep 17 00:00:00 2001 From: Leo Li Date: Tue, 5 Dec 2023 13:20:37 -0500 Subject: [PATCH 23/62] Apply suggestions from code review MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Christoph Stäbler --- test/auth/features/oidc/apiserversource.go | 4 ++-- test/auth/oidc_test.go | 1 - 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/test/auth/features/oidc/apiserversource.go b/test/auth/features/oidc/apiserversource.go index 07c2b5f6178..d1d631d9493 100644 --- a/test/auth/features/oidc/apiserversource.go +++ b/test/auth/features/oidc/apiserversource.go @@ -25,7 +25,7 @@ import ( "knative.dev/eventing/test/rekt/resources/account_role" "knative.dev/eventing/test/rekt/resources/apiserversource" "knative.dev/reconciler-test/pkg/eventshub" - eventasssert "knative.dev/reconciler-test/pkg/eventshub/assert" + eventassert "knative.dev/reconciler-test/pkg/eventshub/assert" "knative.dev/reconciler-test/pkg/feature" "knative.dev/reconciler-test/pkg/manifest" "knative.dev/reconciler-test/pkg/resources/pod" @@ -42,7 +42,7 @@ func ApiserversourceSendEventWithJWT() *feature.Feature { audience := "my-sink-audience" sacmName := feature.MakeRandomK8sName("apiserversource") - f := feature.NewFeatureNamed("Send events to sink") + f := feature.NewFeatureNamed("ApiServerSource send events with OIDC authentication") f.Setup("deploy receiver", eventshub.Install(sink, eventshub.StartReceiver, diff --git a/test/auth/oidc_test.go b/test/auth/oidc_test.go index 74da5407456..1802ca10940 100644 --- a/test/auth/oidc_test.go +++ b/test/auth/oidc_test.go @@ -154,7 +154,6 @@ func TestApiserversourceSendEventWithJWT(t *testing.T) { knative.WithTracingConfig, k8s.WithEventListener, environment.Managed(t), - environment.WithPollTimings(4*time.Second, 12*time.Minute), ) env.Test(ctx, t, oidc.ApiserversourceSendEventWithJWT()) From 751deaafe7e3f939a0b77157449756b846402fd2 Mon Sep 17 00:00:00 2001 From: Leo Li Date: Tue, 5 Dec 2023 13:26:31 -0500 Subject: [PATCH 24/62] Fix the nit error Signed-off-by: Leo Li --- test/auth/features/oidc/apiserversource.go | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/test/auth/features/oidc/apiserversource.go b/test/auth/features/oidc/apiserversource.go index d1d631d9493..658449a25e7 100644 --- a/test/auth/features/oidc/apiserversource.go +++ b/test/auth/features/oidc/apiserversource.go @@ -47,7 +47,7 @@ func ApiserversourceSendEventWithJWT() *feature.Feature { f.Setup("deploy receiver", eventshub.Install(sink, eventshub.StartReceiver, eventshub.OIDCReceiverAudience(audience))) - + f.Setup("Create Service Account for ApiServerSource with RBAC for v1.Event resources", setupAccountAndRoleForApiserversource(sacmName)) @@ -77,8 +77,8 @@ func ApiserversourceSendEventWithJWT() *feature.Feature { f.Stable("ApiServerSource as event source"). Must("delivers events on sink with ref", - eventasssert.OnStore(sink). - Match(eventasssert.MatchKind(eventshub.EventReceived)). + eventassert.OnStore(sink). + Match(eventassert.MatchKind(eventshub.EventReceived)). MatchEvent(test.HasType("dev.knative.apiserver.resource.update")). AtLeast(1), ) From 37e41a8961ae6c3004fbb7bf14839920f6fec07f Mon Sep 17 00:00:00 2001 From: Leo Li Date: Tue, 5 Dec 2023 13:38:32 -0500 Subject: [PATCH 25/62] Move the MakeOIDCRoleBinding() and MakeOIDCRole() to a separate file Signed-off-by: Leo Li --- .../resources/oidc_rolebinding.go | 90 +++++++++++++++++++ .../resources/receive_adapter.go | 66 -------------- 2 files changed, 90 insertions(+), 66 deletions(-) create mode 100644 pkg/reconciler/apiserversource/resources/oidc_rolebinding.go diff --git a/pkg/reconciler/apiserversource/resources/oidc_rolebinding.go b/pkg/reconciler/apiserversource/resources/oidc_rolebinding.go new file mode 100644 index 00000000000..7bc905a8c20 --- /dev/null +++ b/pkg/reconciler/apiserversource/resources/oidc_rolebinding.go @@ -0,0 +1,90 @@ +/* +Copyright 2023 The Knative Authors + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package resources + +import ( + "fmt" + + rbacv1 "k8s.io/api/rbac/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + v1 "knative.dev/eventing/pkg/apis/sources/v1" +) + +// MakeOIDCRole will return the role object config for generating the JWT token +func MakeOIDCRole(source *v1.ApiServerSource) (*rbacv1.Role, error) { + roleName := "create-oidc-token" + + if source.Status.Auth.ServiceAccountName == nil { + return nil, fmt.Errorf("Error when making OIDC Role for apiserversource, as the OIDC service account does not exist") + } + + return &rbacv1.Role{ + ObjectMeta: metav1.ObjectMeta{ + Name: roleName, + Namespace: source.GetNamespace(), + Annotations: map[string]string{ + "description": fmt.Sprintf("Role for OIDC Authentication for %s %q", "ApiServerSource", source.GetName()), + }, + }, + Rules: []rbacv1.PolicyRule{ + rbacv1.PolicyRule{ + APIGroups: []string{""}, + // apiServerSource OIDC service account name, it is in the source.Status, NOT in source.Spec + ResourceNames: []string{*source.Status.Auth.ServiceAccountName}, + Resources: []string{"serviceaccounts/token"}, + Verbs: []string{"create"}, + }, + }, + }, nil + +} + +// MakeOIDCRoleBinding will return the rolebinding object for generating the JWT token +// So that ApiServerSource's service account have access to create the JWT token for it's OIDC service account and the target audience +// Note: it is in the source.Spec, NOT in source.Auth +func MakeOIDCRoleBinding(source *v1.ApiServerSource) (*rbacv1.RoleBinding, error) { + roleName := "create-oidc-token" + roleBindingName := "create-oidc-token" + + if source.Spec.ServiceAccountName == "" { + return nil, fmt.Errorf("Error when making OIDC RoleBinding for apiserversource, as the Spec service account does not exist") + } + + return &rbacv1.RoleBinding{ + ObjectMeta: metav1.ObjectMeta{ + Name: roleBindingName, + Namespace: source.GetNamespace(), + Annotations: map[string]string{ + "description": fmt.Sprintf("Role Binding for OIDC Authentication for %s %q", "ApiServerSource", source.GetName()), + }, + }, + RoleRef: rbacv1.RoleRef{ + APIGroup: "rbac.authorization.k8s.io", + Kind: "Role", + Name: roleName, + }, + Subjects: []rbacv1.Subject{ + { + Kind: "ServiceAccount", + Namespace: source.GetNamespace(), + //Note: apiServerSource service account name, it is in the source.Spec, NOT in source.Status.Auth + Name: source.Spec.ServiceAccountName, + }, + }, + }, nil + +} diff --git a/pkg/reconciler/apiserversource/resources/receive_adapter.go b/pkg/reconciler/apiserversource/resources/receive_adapter.go index d74d0ea8a84..47041bea9c1 100644 --- a/pkg/reconciler/apiserversource/resources/receive_adapter.go +++ b/pkg/reconciler/apiserversource/resources/receive_adapter.go @@ -22,7 +22,6 @@ import ( appsv1 "k8s.io/api/apps/v1" corev1 "k8s.io/api/core/v1" - rbacv1 "k8s.io/api/rbac/v1" "k8s.io/apimachinery/pkg/api/meta" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime/schema" @@ -51,71 +50,6 @@ type ReceiveAdapterArgs struct { AllNamespaces bool } -// MakeOIDCRole will return the role object config for generating the JWT token -func MakeOIDCRole(source *v1.ApiServerSource) (*rbacv1.Role, error) { - roleName := "create-oidc-token" - - if source.Status.Auth.ServiceAccountName == nil { - return nil, fmt.Errorf("Error when making OIDC Role for apiserversource, as the OIDC service account does not exist") - } - - return &rbacv1.Role{ - ObjectMeta: metav1.ObjectMeta{ - Name: roleName, - Namespace: source.GetNamespace(), - Annotations: map[string]string{ - "description": fmt.Sprintf("Role for OIDC Authentication for %s %q", "ApiServerSource", source.GetName()), - }, - }, - Rules: []rbacv1.PolicyRule{ - rbacv1.PolicyRule{ - APIGroups: []string{""}, - // apiServerSource OIDC service account name, it is in the source.Status, NOT in source.Spec - ResourceNames: []string{*source.Status.Auth.ServiceAccountName}, - Resources: []string{"serviceaccounts/token"}, - Verbs: []string{"create"}, - }, - }, - }, nil - -} - -// MakeOIDCRoleBinding will return the rolebinding object for generating the JWT token -// So that ApiServerSource's service account have access to create the JWT token for it's OIDC service account and the target audience -// Note: it is in the source.Spec, NOT in source.Auth -func MakeOIDCRoleBinding(source *v1.ApiServerSource) (*rbacv1.RoleBinding, error) { - roleName := "create-oidc-token" - roleBindingName := "create-oidc-token" - - if source.Spec.ServiceAccountName == "" { - return nil, fmt.Errorf("Error when making OIDC RoleBinding for apiserversource, as the Spec service account does not exist") - } - - return &rbacv1.RoleBinding{ - ObjectMeta: metav1.ObjectMeta{ - Name: roleBindingName, - Namespace: source.GetNamespace(), - Annotations: map[string]string{ - "description": fmt.Sprintf("Role Binding for OIDC Authentication for %s %q", "ApiServerSource", source.GetName()), - }, - }, - RoleRef: rbacv1.RoleRef{ - APIGroup: "rbac.authorization.k8s.io", - Kind: "Role", - Name: roleName, - }, - Subjects: []rbacv1.Subject{ - { - Kind: "ServiceAccount", - Namespace: source.GetNamespace(), - //Note: apiServerSource service account name, it is in the source.Spec, NOT in source.Status.Auth - Name: source.Spec.ServiceAccountName, - }, - }, - }, nil - -} - // MakeReceiveAdapter generates (but does not insert into K8s) the Receive Adapter Deployment for // ApiServer Sources. func MakeReceiveAdapter(args *ReceiveAdapterArgs) (*appsv1.Deployment, error) { From 6861c83de3d7b473c1e572081fe3fa4c575c9fe6 Mon Sep 17 00:00:00 2001 From: Leo Li Date: Wed, 6 Dec 2023 01:19:05 -0500 Subject: [PATCH 26/62] Handle the role and rolebinding update Signed-off-by: Leo Li --- .../apiserversource/apiserversource.go | 48 +++++++++++++++++-- 1 file changed, 44 insertions(+), 4 deletions(-) diff --git a/pkg/reconciler/apiserversource/apiserversource.go b/pkg/reconciler/apiserversource/apiserversource.go index 1f84be8c8fa..55f65158a29 100644 --- a/pkg/reconciler/apiserversource/apiserversource.go +++ b/pkg/reconciler/apiserversource/apiserversource.go @@ -369,16 +369,35 @@ func (r *Reconciler) createOIDCRole(ctx context.Context, source *v1.ApiServerSou roleName := "create-oidc-token" //Call kubeclient and see whether the role exist or not - _, err := r.kubeClientSet.RbacV1().Roles(source.GetNamespace()).Get(ctx, roleName, metav1.GetOptions{}) + role, err := r.kubeClientSet.RbacV1().Roles(source.GetNamespace()).Get(ctx, roleName, metav1.GetOptions{}) + expected, errMakeRole := resources.MakeOIDCRole(source) + + if errMakeRole != nil { + return fmt.Errorf("Cannot create OIDC role for ApiServerSource %s/%s: %w", source.GetName(), source.GetNamespace(), errMakeRole) + } if apierrs.IsNotFound(err) { - role, err := resources.MakeOIDCRole(source) // If the role does not exist, we will call kubeclient to create it + role = expected _, err = r.kubeClientSet.RbacV1().Roles(source.GetNamespace()).Create(ctx, role, metav1.CreateOptions{}) if err != nil { return fmt.Errorf("could not create OIDC service account role %s/%s for %s: %w", source.GetName(), source.GetNamespace(), "ApiServerSource", err) } + } else { + // If the role does exist, we will check whether an update is needed + // By comparing the role's rule + if !equality.Semantic.DeepEqual(role.Rules, expected.Rules) { + // If the role's rules are not equal, we will update the role + role.Rules = expected.Rules + _, err = r.kubeClientSet.RbacV1().Roles(source.GetNamespace()).Update(ctx, role, metav1.UpdateOptions{}) + if err != nil { + return fmt.Errorf("could not update OIDC service account role %s/%s for %s: %w", source.GetName(), source.GetNamespace(), "ApiServerSource", err) + } + } else { + // If the role does exist and no update is needed, we will just return + return nil + } } return nil @@ -391,16 +410,37 @@ func (r *Reconciler) createOIDCRoleBinding(ctx context.Context, source *v1.ApiSe roleBindingName := "create-oidc-token" // Call kubeclient and see whether the roleBinding exist or not - _, err := r.kubeClientSet.RbacV1().RoleBindings(source.GetNamespace()).Get(ctx, roleBindingName, metav1.GetOptions{}) + roleBinding, err := r.kubeClientSet.RbacV1().RoleBindings(source.GetNamespace()).Get(ctx, roleBindingName, metav1.GetOptions{}) + expected, errMakeRoleBinding := resources.MakeOIDCRoleBinding(source) + + if errMakeRoleBinding != nil { + return fmt.Errorf("Cannot create OIDC roleBinding for ApiServerSource %s/%s: %w", source.GetName(), source.GetNamespace(), errMakeRoleBinding) + } if apierrs.IsNotFound(err) { - roleBinding, err := resources.MakeOIDCRoleBinding(source) // If the role does not exist, we will call kubeclient to create it + roleBinding = expected _, err = r.kubeClientSet.RbacV1().RoleBindings(source.GetNamespace()).Create(ctx, roleBinding, metav1.CreateOptions{}) if err != nil { return fmt.Errorf("could not create OIDC service account rolebinding %s/%s for %s: %w", source.GetName(), source.GetNamespace(), "apiserversource", err) } + } else { + // If the role does exist, we will check whether an update is needed + // By comparing the role's rule + if !equality.Semantic.DeepEqual(roleBinding.RoleRef, expected.RoleRef) || !equality.Semantic.DeepEqual(roleBinding.Subjects, expected.Subjects) { + // If the role's rules are not equal, we will update the role + roleBinding.RoleRef = expected.RoleRef + roleBinding.Subjects = expected.Subjects + _, err = r.kubeClientSet.RbacV1().RoleBindings(source.GetNamespace()).Update(ctx, roleBinding, metav1.UpdateOptions{}) + if err != nil { + return fmt.Errorf("could not update OIDC service account rolebinding %s/%s for %s: %w", source.GetName(), source.GetNamespace(), "apiserversource", err) + } + } else { + // If the role does exist and no update is needed, we will just return + return nil + } } + return nil } From af5e3c0686d5e30121c6d8d8369f782fea60d2bf Mon Sep 17 00:00:00 2001 From: Leo Li Date: Wed, 6 Dec 2023 01:23:35 -0500 Subject: [PATCH 27/62] Fix the typo Signed-off-by: Leo Li --- test/upgrade/prober/receiver.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/upgrade/prober/receiver.go b/test/upgrade/prober/receiver.go index a706871a5c3..ca2dcf37c54 100644 --- a/test/upgrade/prober/receiver.go +++ b/test/upgrade/prober/receiver.go @@ -74,7 +74,7 @@ func (p *prober) deployReceiverService() { p.client.CreateServiceOrFail(service) } -func (p *prober) iverDeployment() *appsv1.Deployment { +func (p *prober) createReceiverDeployment() *appsv1.Deployment { var replicas int32 = 1 return &appsv1.Deployment{ ObjectMeta: metav1.ObjectMeta{ From dcc0dd0463b8c9235d3debbb600d98197ea6c7b7 Mon Sep 17 00:00:00 2001 From: Leo Li Date: Wed, 6 Dec 2023 11:36:48 -0500 Subject: [PATCH 28/62] Update pkg/adapter/v2/cloudevents.go MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Christoph Stäbler --- pkg/adapter/v2/cloudevents.go | 14 -------------- 1 file changed, 14 deletions(-) diff --git a/pkg/adapter/v2/cloudevents.go b/pkg/adapter/v2/cloudevents.go index 3395d480b2a..9987e50ec16 100644 --- a/pkg/adapter/v2/cloudevents.go +++ b/pkg/adapter/v2/cloudevents.go @@ -249,20 +249,6 @@ var _ cloudevents.Client = (*client)(nil) func (c *client) Send(ctx context.Context, out event.Event) protocol.Result { c.applyOverrides(&out) - //// If the sink has audience and the OIDC service account, then we need to request the JWT token - //if c.audience != nil && c.serviceAccountName != nil { - // // Request the JWT token for the given service account - // jwt, err := c.oidcTokenProvider.GetJWT(*c.serviceAccountName, *c.audience) - // if err != nil { - // return protocol.NewResult("%w", err) - // } - // - // // Appending the auth token to the outgoing request - // headers := http.HeaderFrom(ctx) - // headers.Set("Authorization", fmt.Sprintf("Bearer %s", jwt)) - // ctx = http.WithCustomHeader(ctx, headers) - //} - err := c.appendAuthHeader(&ctx) if err != nil { return err From 8474dbea7d827e38ea1818ff791e4014936c2be0 Mon Sep 17 00:00:00 2001 From: Leo Li Date: Wed, 6 Dec 2023 11:36:55 -0500 Subject: [PATCH 29/62] Update pkg/adapter/v2/cloudevents.go MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Christoph Stäbler --- pkg/adapter/v2/cloudevents.go | 14 -------------- 1 file changed, 14 deletions(-) diff --git a/pkg/adapter/v2/cloudevents.go b/pkg/adapter/v2/cloudevents.go index 9987e50ec16..b427d315455 100644 --- a/pkg/adapter/v2/cloudevents.go +++ b/pkg/adapter/v2/cloudevents.go @@ -263,20 +263,6 @@ func (c *client) Send(ctx context.Context, out event.Event) protocol.Result { func (c *client) Request(ctx context.Context, out event.Event) (*event.Event, protocol.Result) { c.applyOverrides(&out) - //// If the sink has audience and the OIDC service account, then we need to request the JWT token - //if c.audience != nil && c.serviceAccountName != nil { - // // Request the JWT token for the given service account - // jwt, err := c.oidcTokenProvider.GetJWT(*c.serviceAccountName, *c.audience) - // if err != nil { - // return nil, protocol.NewResult("%w", err) - // } - // - // // Appending the auth token to the outgoing request - // headers := http.HeaderFrom(ctx) - // headers.Set("Authorization", fmt.Sprintf("Bearer %s", jwt)) - // ctx = http.WithCustomHeader(ctx, headers) - //} - err := c.appendAuthHeader(&ctx) if err != nil { return nil, err From be9f52dcbf51336271f158a273ee124295cb55fe Mon Sep 17 00:00:00 2001 From: Leo Li Date: Wed, 6 Dec 2023 11:37:31 -0500 Subject: [PATCH 30/62] Update pkg/adapter/v2/config.go MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Christoph Stäbler --- pkg/adapter/v2/config.go | 1 - 1 file changed, 1 deletion(-) diff --git a/pkg/adapter/v2/config.go b/pkg/adapter/v2/config.go index bf20c14ece4..946cd270efc 100644 --- a/pkg/adapter/v2/config.go +++ b/pkg/adapter/v2/config.go @@ -189,7 +189,6 @@ func (e *EnvConfig) GetSink() string { } func (e *EnvConfig) GetServiceAccountName() *types.NamespacedName { - if e.ServiceAccountName != nil { return &types.NamespacedName{ Namespace: e.Namespace, From 12cbf55d472ae73d6f9ab3090934dbc70f410708 Mon Sep 17 00:00:00 2001 From: Leo Li Date: Wed, 6 Dec 2023 11:37:54 -0500 Subject: [PATCH 31/62] Update pkg/reconciler/apiserversource/resources/oidc_rolebinding.go MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Christoph Stäbler --- pkg/reconciler/apiserversource/resources/oidc_rolebinding.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkg/reconciler/apiserversource/resources/oidc_rolebinding.go b/pkg/reconciler/apiserversource/resources/oidc_rolebinding.go index 7bc905a8c20..41e76ad78ce 100644 --- a/pkg/reconciler/apiserversource/resources/oidc_rolebinding.go +++ b/pkg/reconciler/apiserversource/resources/oidc_rolebinding.go @@ -69,7 +69,7 @@ func MakeOIDCRoleBinding(source *v1.ApiServerSource) (*rbacv1.RoleBinding, error Name: roleBindingName, Namespace: source.GetNamespace(), Annotations: map[string]string{ - "description": fmt.Sprintf("Role Binding for OIDC Authentication for %s %q", "ApiServerSource", source.GetName()), + "description": fmt.Sprintf("Role Binding for OIDC Authentication for ApiServerSource %q", source.GetName()), }, }, RoleRef: rbacv1.RoleRef{ From 43dbcfbc3c37cd4acc78e8b0b2553442e3095f9e Mon Sep 17 00:00:00 2001 From: Leo Li Date: Wed, 6 Dec 2023 11:38:08 -0500 Subject: [PATCH 32/62] Update pkg/reconciler/apiserversource/resources/receive_adapter.go MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Christoph Stäbler --- pkg/reconciler/apiserversource/resources/receive_adapter.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkg/reconciler/apiserversource/resources/receive_adapter.go b/pkg/reconciler/apiserversource/resources/receive_adapter.go index 47041bea9c1..4f05730f2ca 100644 --- a/pkg/reconciler/apiserversource/resources/receive_adapter.go +++ b/pkg/reconciler/apiserversource/resources/receive_adapter.go @@ -188,7 +188,7 @@ func makeEnv(args *ReceiveAdapterArgs) ([]corev1.EnvVar, error) { }) } - if args.Source.Status.Auth != nil { + if args.Source.Status.Auth != nil && args.Source.Status.Auth.ServiceAccountName != nil { envs = append(envs, corev1.EnvVar{ Name: adapter.EnvConfigOIDCServiceAccount, Value: *args.Source.Status.Auth.ServiceAccountName, From 2e3191cd4b842f68e9998b53aa67b91af75876a6 Mon Sep 17 00:00:00 2001 From: Leo Li Date: Wed, 6 Dec 2023 11:38:19 -0500 Subject: [PATCH 33/62] Update pkg/adapter/v2/config.go MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Christoph Stäbler --- pkg/adapter/v2/config.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkg/adapter/v2/config.go b/pkg/adapter/v2/config.go index 946cd270efc..893c98d4494 100644 --- a/pkg/adapter/v2/config.go +++ b/pkg/adapter/v2/config.go @@ -126,7 +126,7 @@ type EnvConfigAccessor interface { // Get the audience of the target sink. GetAudience() *string - // Get the service account name to use for the adapter. + // GetServiceAccountName gets the service account name to use for the adapter. GetServiceAccountName() *types.NamespacedName // Get the namespace of the adapter. From d8a8b535b92b352e9132b6bb2d407a0f29f767b1 Mon Sep 17 00:00:00 2001 From: Leo Li Date: Wed, 6 Dec 2023 11:38:45 -0500 Subject: [PATCH 34/62] Update pkg/adapter/v2/config.go MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Christoph Stäbler --- pkg/adapter/v2/config.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkg/adapter/v2/config.go b/pkg/adapter/v2/config.go index 893c98d4494..9f644b0527b 100644 --- a/pkg/adapter/v2/config.go +++ b/pkg/adapter/v2/config.go @@ -123,7 +123,7 @@ type EnvConfigAccessor interface { // GetCACerts gets the CACerts of the Sink. GetCACerts() *string - // Get the audience of the target sink. + // GetAudience gets the audience of the target sink. GetAudience() *string // GetServiceAccountName gets the service account name to use for the adapter. From a7468500825bc58e407181bed620ff56a755a60a Mon Sep 17 00:00:00 2001 From: Leo Li Date: Wed, 6 Dec 2023 11:38:59 -0500 Subject: [PATCH 35/62] Update pkg/reconciler/apiserversource/resources/oidc_rolebinding.go MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Christoph Stäbler --- pkg/reconciler/apiserversource/resources/oidc_rolebinding.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkg/reconciler/apiserversource/resources/oidc_rolebinding.go b/pkg/reconciler/apiserversource/resources/oidc_rolebinding.go index 41e76ad78ce..c6bf0a69445 100644 --- a/pkg/reconciler/apiserversource/resources/oidc_rolebinding.go +++ b/pkg/reconciler/apiserversource/resources/oidc_rolebinding.go @@ -37,7 +37,7 @@ func MakeOIDCRole(source *v1.ApiServerSource) (*rbacv1.Role, error) { Name: roleName, Namespace: source.GetNamespace(), Annotations: map[string]string{ - "description": fmt.Sprintf("Role for OIDC Authentication for %s %q", "ApiServerSource", source.GetName()), + "description": fmt.Sprintf("Role for OIDC Authentication for ApiServerSource %q", source.GetName()), }, }, Rules: []rbacv1.PolicyRule{ From 0630d3a70599a3410b3e1458954c0277ee189b57 Mon Sep 17 00:00:00 2001 From: Leo Li Date: Wed, 6 Dec 2023 12:38:59 -0500 Subject: [PATCH 36/62] Fix the majority of the review comments except for the role lister. Signed-off-by: Leo Li --- pkg/adapter/v2/cloudevents.go | 35 +++++++++++-------- pkg/adapter/v2/config.go | 6 ++-- .../apiserversource/apiserversource.go | 6 ++-- .../resources/oidc_rolebinding.go | 18 ++++++++-- 4 files changed, 41 insertions(+), 24 deletions(-) diff --git a/pkg/adapter/v2/cloudevents.go b/pkg/adapter/v2/cloudevents.go index b427d315455..bb860419f06 100644 --- a/pkg/adapter/v2/cloudevents.go +++ b/pkg/adapter/v2/cloudevents.go @@ -208,7 +208,7 @@ func NewClient(cfg ClientConfig) (Client, error) { if cfg.Env != nil { client.audience = cfg.Env.GetAudience() - client.serviceAccountName = cfg.Env.GetServiceAccountName() + client.serviceAccountName = cfg.Env.GetOIDCServiceAccountName() } return client, nil @@ -248,10 +248,13 @@ var _ cloudevents.Client = (*client)(nil) // Send implements client.Send func (c *client) Send(ctx context.Context, out event.Event) protocol.Result { c.applyOverrides(&out) + var err error - err := c.appendAuthHeader(&ctx) - if err != nil { - return err + if c.audience != nil && c.serviceAccountName != nil { + ctx, err = c.appendAuthHeader(ctx) + if err != nil { + return err + } } res := c.ceClient.Send(ctx, out) @@ -262,11 +265,15 @@ func (c *client) Send(ctx context.Context, out event.Event) protocol.Result { // Request implements client.Request func (c *client) Request(ctx context.Context, out event.Event) (*event.Event, protocol.Result) { c.applyOverrides(&out) + var err error - err := c.appendAuthHeader(&ctx) - if err != nil { - return nil, err + if c.audience != nil && c.serviceAccountName != nil{ + ctx, err = c.appendAuthHeader(ctx) + if err != nil { + return nil, err + } } + resp, res := c.ceClient.Request(ctx, out) c.reportMetrics(ctx, out, res) return resp, res @@ -396,20 +403,18 @@ func tracecontextMiddleware(h nethttp.Handler) nethttp.Handler { // When OIDC is enabled, appendAuthHeader will request the JWT token from the tokenProvider and append it to every request // it has interaction with, if source's OIDC service account (source.Status.Auth.ServiceAccountName) and destination's // audience are present. -func (c *client) appendAuthHeader(ctx *context.Context) error { - // If the sink has audience and the OIDC service account, then we need to request the JWT token - if c.audience != nil && c.serviceAccountName != nil { +func (c *client) appendAuthHeader(ctx context.Context) (context.Context,error) { // Request the JWT token for the given service account jwt, err := c.oidcTokenProvider.GetJWT(*c.serviceAccountName, *c.audience) if err != nil { - return protocol.NewResult("%w", err) + return ctx, protocol.NewResult("Failed when appending the Authorization header to the outgoing request %w", err) } // Appending the auth token to the outgoing request - headers := http.HeaderFrom(*ctx) + headers := http.HeaderFrom(ctx) headers.Set("Authorization", fmt.Sprintf("Bearer %s", jwt)) - *ctx = http.WithCustomHeader(*ctx, headers) - } + ctx = http.WithCustomHeader(ctx, headers) + - return nil + return ctx,nil } diff --git a/pkg/adapter/v2/config.go b/pkg/adapter/v2/config.go index 9f644b0527b..38a9fbb2d39 100644 --- a/pkg/adapter/v2/config.go +++ b/pkg/adapter/v2/config.go @@ -126,8 +126,8 @@ type EnvConfigAccessor interface { // GetAudience gets the audience of the target sink. GetAudience() *string - // GetServiceAccountName gets the service account name to use for the adapter. - GetServiceAccountName() *types.NamespacedName + // GetOIDCServiceAccountName gets the service account name to use for the adapter. + GetOIDCServiceAccountName() *types.NamespacedName // Get the namespace of the adapter. GetNamespace() string @@ -188,7 +188,7 @@ func (e *EnvConfig) GetSink() string { return e.Sink } -func (e *EnvConfig) GetServiceAccountName() *types.NamespacedName { +func (e *EnvConfig) GetOIDCServiceAccountName() *types.NamespacedName { if e.ServiceAccountName != nil { return &types.NamespacedName{ Namespace: e.Namespace, diff --git a/pkg/reconciler/apiserversource/apiserversource.go b/pkg/reconciler/apiserversource/apiserversource.go index 55f65158a29..942078af153 100644 --- a/pkg/reconciler/apiserversource/apiserversource.go +++ b/pkg/reconciler/apiserversource/apiserversource.go @@ -20,7 +20,6 @@ import ( "context" "encoding/json" "fmt" - "sort" apierrs "k8s.io/apimachinery/pkg/api/errors" @@ -366,10 +365,11 @@ func (r *Reconciler) createCloudEventAttributes(src *v1.ApiServerSource) ([]duck // createOIDCRole: this function will call resources package to get the role object // and then pass to kubeclient to make the actual OIDC role func (r *Reconciler) createOIDCRole(ctx context.Context, source *v1.ApiServerSource) error { - roleName := "create-oidc-token" + roleName := resources.CreateOIDCTokenRoleName(source) //Call kubeclient and see whether the role exist or not role, err := r.kubeClientSet.RbacV1().Roles(source.GetNamespace()).Get(ctx, roleName, metav1.GetOptions{}) + expected, errMakeRole := resources.MakeOIDCRole(source) if errMakeRole != nil { @@ -407,7 +407,7 @@ func (r *Reconciler) createOIDCRole(ctx context.Context, source *v1.ApiServerSou // createOIDCRoleBinding: this function will call resources package to get the rolebinding object // and then pass to kubeclient to make the actual OIDC rolebinding func (r *Reconciler) createOIDCRoleBinding(ctx context.Context, source *v1.ApiServerSource) error { - roleBindingName := "create-oidc-token" + roleBindingName := resources.CreateOIDCTokenRoleBindingName(source) // Call kubeclient and see whether the roleBinding exist or not roleBinding, err := r.kubeClientSet.RbacV1().RoleBindings(source.GetNamespace()).Get(ctx, roleBindingName, metav1.GetOptions{}) diff --git a/pkg/reconciler/apiserversource/resources/oidc_rolebinding.go b/pkg/reconciler/apiserversource/resources/oidc_rolebinding.go index c6bf0a69445..202496bf85c 100644 --- a/pkg/reconciler/apiserversource/resources/oidc_rolebinding.go +++ b/pkg/reconciler/apiserversource/resources/oidc_rolebinding.go @@ -18,15 +18,27 @@ package resources import ( "fmt" + "knative.dev/pkg/kmeta" rbacv1 "k8s.io/api/rbac/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" v1 "knative.dev/eventing/pkg/apis/sources/v1" ) +// createOIDCTokenRoleName will return the name of the role for creating the JWT token +func CreateOIDCTokenRoleName (source *v1.ApiServerSource) (string){ + return kmeta.ChildName(source.GetName(),"create-oidc-token-role") +} + +// createOIDCTokenRoleBindingName will return the name of the rolebinding for creating the JWT token +func CreateOIDCTokenRoleBindingName (source *v1.ApiServerSource) (string){ + return kmeta.ChildName(source.GetName(),"create-oidc-token-rolebinding") +} + + // MakeOIDCRole will return the role object config for generating the JWT token func MakeOIDCRole(source *v1.ApiServerSource) (*rbacv1.Role, error) { - roleName := "create-oidc-token" + roleName := CreateOIDCTokenRoleName(source) if source.Status.Auth.ServiceAccountName == nil { return nil, fmt.Errorf("Error when making OIDC Role for apiserversource, as the OIDC service account does not exist") @@ -57,8 +69,8 @@ func MakeOIDCRole(source *v1.ApiServerSource) (*rbacv1.Role, error) { // So that ApiServerSource's service account have access to create the JWT token for it's OIDC service account and the target audience // Note: it is in the source.Spec, NOT in source.Auth func MakeOIDCRoleBinding(source *v1.ApiServerSource) (*rbacv1.RoleBinding, error) { - roleName := "create-oidc-token" - roleBindingName := "create-oidc-token" + roleName := CreateOIDCTokenRoleName(source) + roleBindingName := CreateOIDCTokenRoleBindingName(source) if source.Spec.ServiceAccountName == "" { return nil, fmt.Errorf("Error when making OIDC RoleBinding for apiserversource, as the Spec service account does not exist") From 8961e967183230b0e215d26921dd216f6c5a2b10 Mon Sep 17 00:00:00 2001 From: Leo Li Date: Thu, 7 Dec 2023 02:24:12 -0500 Subject: [PATCH 37/62] Fix the majority of the review comments except for the role lister. Signed-off-by: Leo Li --- pkg/reconciler/apiserversource/resources/oidc_rolebinding.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkg/reconciler/apiserversource/resources/oidc_rolebinding.go b/pkg/reconciler/apiserversource/resources/oidc_rolebinding.go index 202496bf85c..ef321df82a5 100644 --- a/pkg/reconciler/apiserversource/resources/oidc_rolebinding.go +++ b/pkg/reconciler/apiserversource/resources/oidc_rolebinding.go @@ -40,7 +40,7 @@ func CreateOIDCTokenRoleBindingName (source *v1.ApiServerSource) (string){ func MakeOIDCRole(source *v1.ApiServerSource) (*rbacv1.Role, error) { roleName := CreateOIDCTokenRoleName(source) - if source.Status.Auth.ServiceAccountName == nil { + if source.Status.Auth == nil || source.Status.Auth.ServiceAccountName == nil { return nil, fmt.Errorf("Error when making OIDC Role for apiserversource, as the OIDC service account does not exist") } From 6821cd0fca001196e8e6b7c61ee4a946a10a66cf Mon Sep 17 00:00:00 2001 From: Leo Li Date: Thu, 7 Dec 2023 02:25:56 -0500 Subject: [PATCH 38/62] Gofmt and goimports Signed-off-by: Leo Li --- pkg/adapter/v2/cloudevents.go | 25 +++++++++---------- .../resources/oidc_rolebinding.go | 10 ++++---- 2 files changed, 17 insertions(+), 18 deletions(-) diff --git a/pkg/adapter/v2/cloudevents.go b/pkg/adapter/v2/cloudevents.go index bb860419f06..f2a118c9fc0 100644 --- a/pkg/adapter/v2/cloudevents.go +++ b/pkg/adapter/v2/cloudevents.go @@ -267,7 +267,7 @@ func (c *client) Request(ctx context.Context, out event.Event) (*event.Event, pr c.applyOverrides(&out) var err error - if c.audience != nil && c.serviceAccountName != nil{ + if c.audience != nil && c.serviceAccountName != nil { ctx, err = c.appendAuthHeader(ctx) if err != nil { return nil, err @@ -403,18 +403,17 @@ func tracecontextMiddleware(h nethttp.Handler) nethttp.Handler { // When OIDC is enabled, appendAuthHeader will request the JWT token from the tokenProvider and append it to every request // it has interaction with, if source's OIDC service account (source.Status.Auth.ServiceAccountName) and destination's // audience are present. -func (c *client) appendAuthHeader(ctx context.Context) (context.Context,error) { - // Request the JWT token for the given service account - jwt, err := c.oidcTokenProvider.GetJWT(*c.serviceAccountName, *c.audience) - if err != nil { - return ctx, protocol.NewResult("Failed when appending the Authorization header to the outgoing request %w", err) - } - - // Appending the auth token to the outgoing request - headers := http.HeaderFrom(ctx) - headers.Set("Authorization", fmt.Sprintf("Bearer %s", jwt)) - ctx = http.WithCustomHeader(ctx, headers) +func (c *client) appendAuthHeader(ctx context.Context) (context.Context, error) { + // Request the JWT token for the given service account + jwt, err := c.oidcTokenProvider.GetJWT(*c.serviceAccountName, *c.audience) + if err != nil { + return ctx, protocol.NewResult("Failed when appending the Authorization header to the outgoing request %w", err) + } + // Appending the auth token to the outgoing request + headers := http.HeaderFrom(ctx) + headers.Set("Authorization", fmt.Sprintf("Bearer %s", jwt)) + ctx = http.WithCustomHeader(ctx, headers) - return ctx,nil + return ctx, nil } diff --git a/pkg/reconciler/apiserversource/resources/oidc_rolebinding.go b/pkg/reconciler/apiserversource/resources/oidc_rolebinding.go index ef321df82a5..4f688df773b 100644 --- a/pkg/reconciler/apiserversource/resources/oidc_rolebinding.go +++ b/pkg/reconciler/apiserversource/resources/oidc_rolebinding.go @@ -18,6 +18,7 @@ package resources import ( "fmt" + "knative.dev/pkg/kmeta" rbacv1 "k8s.io/api/rbac/v1" @@ -26,16 +27,15 @@ import ( ) // createOIDCTokenRoleName will return the name of the role for creating the JWT token -func CreateOIDCTokenRoleName (source *v1.ApiServerSource) (string){ - return kmeta.ChildName(source.GetName(),"create-oidc-token-role") +func CreateOIDCTokenRoleName(source *v1.ApiServerSource) string { + return kmeta.ChildName(source.GetName(), "create-oidc-token-role") } // createOIDCTokenRoleBindingName will return the name of the rolebinding for creating the JWT token -func CreateOIDCTokenRoleBindingName (source *v1.ApiServerSource) (string){ - return kmeta.ChildName(source.GetName(),"create-oidc-token-rolebinding") +func CreateOIDCTokenRoleBindingName(source *v1.ApiServerSource) string { + return kmeta.ChildName(source.GetName(), "create-oidc-token-rolebinding") } - // MakeOIDCRole will return the role object config for generating the JWT token func MakeOIDCRole(source *v1.ApiServerSource) (*rbacv1.Role, error) { roleName := CreateOIDCTokenRoleName(source) From 7b87e70e20bfb85959aa1f9aa398a645128cc99c Mon Sep 17 00:00:00 2001 From: Leo Li Date: Thu, 7 Dec 2023 02:49:51 -0500 Subject: [PATCH 39/62] Update the injection dependency Signed-off-by: Leo Li --- .../kube/informers/rbac/v1/role/role.go | 52 +++++++++++++++++++ vendor/modules.txt | 1 + 2 files changed, 53 insertions(+) create mode 100644 vendor/knative.dev/pkg/client/injection/kube/informers/rbac/v1/role/role.go diff --git a/vendor/knative.dev/pkg/client/injection/kube/informers/rbac/v1/role/role.go b/vendor/knative.dev/pkg/client/injection/kube/informers/rbac/v1/role/role.go new file mode 100644 index 00000000000..14651f3f4fc --- /dev/null +++ b/vendor/knative.dev/pkg/client/injection/kube/informers/rbac/v1/role/role.go @@ -0,0 +1,52 @@ +/* +Copyright 2022 The Knative Authors + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +// Code generated by injection-gen. DO NOT EDIT. + +package role + +import ( + context "context" + + v1 "k8s.io/client-go/informers/rbac/v1" + factory "knative.dev/pkg/client/injection/kube/informers/factory" + controller "knative.dev/pkg/controller" + injection "knative.dev/pkg/injection" + logging "knative.dev/pkg/logging" +) + +func init() { + injection.Default.RegisterInformer(withInformer) +} + +// Key is used for associating the Informer inside the context.Context. +type Key struct{} + +func withInformer(ctx context.Context) (context.Context, controller.Informer) { + f := factory.Get(ctx) + inf := f.Rbac().V1().Roles() + return context.WithValue(ctx, Key{}, inf), inf.Informer() +} + +// Get extracts the typed informer from the context. +func Get(ctx context.Context) v1.RoleInformer { + untyped := ctx.Value(Key{}) + if untyped == nil { + logging.FromContext(ctx).Panic( + "Unable to fetch k8s.io/client-go/informers/rbac/v1.RoleInformer from context.") + } + return untyped.(v1.RoleInformer) +} diff --git a/vendor/modules.txt b/vendor/modules.txt index 8aab6a5c826..35f85b864b0 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -1263,6 +1263,7 @@ knative.dev/pkg/client/injection/kube/informers/core/v1/serviceaccount knative.dev/pkg/client/injection/kube/informers/core/v1/serviceaccount/fake knative.dev/pkg/client/injection/kube/informers/factory knative.dev/pkg/client/injection/kube/informers/factory/fake +knative.dev/pkg/client/injection/kube/informers/rbac/v1/role knative.dev/pkg/client/injection/kube/informers/rbac/v1/rolebinding knative.dev/pkg/client/injection/kube/informers/rbac/v1/rolebinding/fake knative.dev/pkg/client/injection/kube/reconciler/core/v1/namespace From 4a68425aa3e184baf6dedb6460b13d0dce6a6c3b Mon Sep 17 00:00:00 2001 From: Leo Li Date: Thu, 7 Dec 2023 02:50:41 -0500 Subject: [PATCH 40/62] Use roleLister and roleBindingLister Signed-off-by: Leo Li --- pkg/reconciler/apiserversource/apiserversource.go | 8 ++++++-- pkg/reconciler/apiserversource/controller.go | 7 +++++++ 2 files changed, 13 insertions(+), 2 deletions(-) diff --git a/pkg/reconciler/apiserversource/apiserversource.go b/pkg/reconciler/apiserversource/apiserversource.go index 942078af153..07eae746dbf 100644 --- a/pkg/reconciler/apiserversource/apiserversource.go +++ b/pkg/reconciler/apiserversource/apiserversource.go @@ -22,6 +22,8 @@ import ( "fmt" "sort" + rbacv1listers "k8s.io/client-go/listers/rbac/v1" + apierrs "k8s.io/apimachinery/pkg/api/errors" "go.uber.org/zap" @@ -77,6 +79,8 @@ type Reconciler struct { namespaceLister clientv1.NamespaceLister serviceAccountLister clientv1.ServiceAccountLister + roleLister rbacv1listers.RoleLister + roleBindingLister rbacv1listers.RoleBindingLister } var _ apiserversourcereconciler.Interface = (*Reconciler)(nil) @@ -368,7 +372,7 @@ func (r *Reconciler) createOIDCRole(ctx context.Context, source *v1.ApiServerSou roleName := resources.CreateOIDCTokenRoleName(source) //Call kubeclient and see whether the role exist or not - role, err := r.kubeClientSet.RbacV1().Roles(source.GetNamespace()).Get(ctx, roleName, metav1.GetOptions{}) + role, err := r.roleLister.Roles(source.GetNamespace()).Get(roleName) expected, errMakeRole := resources.MakeOIDCRole(source) @@ -410,7 +414,7 @@ func (r *Reconciler) createOIDCRoleBinding(ctx context.Context, source *v1.ApiSe roleBindingName := resources.CreateOIDCTokenRoleBindingName(source) // Call kubeclient and see whether the roleBinding exist or not - roleBinding, err := r.kubeClientSet.RbacV1().RoleBindings(source.GetNamespace()).Get(ctx, roleBindingName, metav1.GetOptions{}) + roleBinding, err := r.roleBindingLister.RoleBindings(source.GetNamespace()).Get(roleBindingName) expected, errMakeRoleBinding := resources.MakeOIDCRoleBinding(source) if errMakeRoleBinding != nil { diff --git a/pkg/reconciler/apiserversource/controller.go b/pkg/reconciler/apiserversource/controller.go index f7fb4b1e1f0..3685f387c56 100644 --- a/pkg/reconciler/apiserversource/controller.go +++ b/pkg/reconciler/apiserversource/controller.go @@ -38,6 +38,8 @@ import ( apiserversourceinformer "knative.dev/eventing/pkg/client/injection/informers/sources/v1/apiserversource" apiserversourcereconciler "knative.dev/eventing/pkg/client/injection/reconciler/sources/v1/apiserversource" serviceaccountinformer "knative.dev/pkg/client/injection/kube/informers/core/v1/serviceaccount" + roleinformer "knative.dev/pkg/client/injection/kube/informers/rbac/v1/role" + rolebindinginformer "knative.dev/pkg/client/injection/kube/informers/rbac/v1/rolebinding" ) // envConfig will be used to extract the required environment variables using @@ -59,6 +61,9 @@ func NewController( namespaceInformer := namespace.Get(ctx) serviceaccountInformer := serviceaccountinformer.Get(ctx) + roleInformer := roleinformer.Get(ctx) + rolebindingInformer := rolebindinginformer.Get(ctx) + var globalResync func(obj interface{}) featureStore := feature.NewStore(logging.FromContext(ctx).Named("feature-config-store"), func(name string, value interface{}) { @@ -74,6 +79,8 @@ func NewController( configs: reconcilersource.WatchConfigurations(ctx, component, cmw), namespaceLister: namespaceInformer.Lister(), serviceAccountLister: serviceaccountInformer.Lister(), + roleLister: roleInformer.Lister(), + roleBindingLister: rolebindingInformer.Lister(), } env := &envConfig{} From 13cc267e57fd69bd5f36cbb9407c0c95fcd77931 Mon Sep 17 00:00:00 2001 From: Leo Li Date: Mon, 11 Dec 2023 00:47:24 -0500 Subject: [PATCH 41/62] Apply suggestions from code review MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Christoph Stäbler --- pkg/adapter/v2/cloudevents.go | 2 +- .../apiserversource/resources/oidc_rolebinding.go | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/pkg/adapter/v2/cloudevents.go b/pkg/adapter/v2/cloudevents.go index f2a118c9fc0..842b23b5483 100644 --- a/pkg/adapter/v2/cloudevents.go +++ b/pkg/adapter/v2/cloudevents.go @@ -403,7 +403,7 @@ func tracecontextMiddleware(h nethttp.Handler) nethttp.Handler { // When OIDC is enabled, appendAuthHeader will request the JWT token from the tokenProvider and append it to every request // it has interaction with, if source's OIDC service account (source.Status.Auth.ServiceAccountName) and destination's // audience are present. -func (c *client) appendAuthHeader(ctx context.Context) (context.Context, error) { +func (c *client) withAuthHeader(ctx context.Context) (context.Context, error) { // Request the JWT token for the given service account jwt, err := c.oidcTokenProvider.GetJWT(*c.serviceAccountName, *c.audience) if err != nil { diff --git a/pkg/reconciler/apiserversource/resources/oidc_rolebinding.go b/pkg/reconciler/apiserversource/resources/oidc_rolebinding.go index 4f688df773b..616f693cee3 100644 --- a/pkg/reconciler/apiserversource/resources/oidc_rolebinding.go +++ b/pkg/reconciler/apiserversource/resources/oidc_rolebinding.go @@ -26,13 +26,13 @@ import ( v1 "knative.dev/eventing/pkg/apis/sources/v1" ) -// createOIDCTokenRoleName will return the name of the role for creating the JWT token -func CreateOIDCTokenRoleName(source *v1.ApiServerSource) string { +// GetOIDCTokenRoleName will return the name of the role for creating the JWT token +func GetOIDCTokenRoleName(source *v1.ApiServerSource) string { return kmeta.ChildName(source.GetName(), "create-oidc-token-role") } -// createOIDCTokenRoleBindingName will return the name of the rolebinding for creating the JWT token -func CreateOIDCTokenRoleBindingName(source *v1.ApiServerSource) string { +// GetOIDCTokenRoleBindingName will return the name of the rolebinding for creating the JWT token +func GetOIDCTokenRoleBindingName(source *v1.ApiServerSource) string { return kmeta.ChildName(source.GetName(), "create-oidc-token-rolebinding") } From 36e70befaf916d4c84182c6b887b5a7d7e15692a Mon Sep 17 00:00:00 2001 From: Leo Li Date: Mon, 11 Dec 2023 01:01:42 -0500 Subject: [PATCH 42/62] Update the nit function name change Signed-off-by: Leo Li --- pkg/adapter/v2/cloudevents.go | 6 +++--- pkg/adapter/v2/config.go | 8 ++++---- pkg/reconciler/apiserversource/apiserversource.go | 4 ++-- .../apiserversource/resources/oidc_rolebinding.go | 6 +++--- 4 files changed, 12 insertions(+), 12 deletions(-) diff --git a/pkg/adapter/v2/cloudevents.go b/pkg/adapter/v2/cloudevents.go index 842b23b5483..2efdeac0490 100644 --- a/pkg/adapter/v2/cloudevents.go +++ b/pkg/adapter/v2/cloudevents.go @@ -251,7 +251,7 @@ func (c *client) Send(ctx context.Context, out event.Event) protocol.Result { var err error if c.audience != nil && c.serviceAccountName != nil { - ctx, err = c.appendAuthHeader(ctx) + ctx, err = c.withAuthHeader(ctx) if err != nil { return err } @@ -268,7 +268,7 @@ func (c *client) Request(ctx context.Context, out event.Event) (*event.Event, pr var err error if c.audience != nil && c.serviceAccountName != nil { - ctx, err = c.appendAuthHeader(ctx) + ctx, err = c.withAuthHeader(ctx) if err != nil { return nil, err } @@ -400,7 +400,7 @@ func tracecontextMiddleware(h nethttp.Handler) nethttp.Handler { } } -// When OIDC is enabled, appendAuthHeader will request the JWT token from the tokenProvider and append it to every request +// When OIDC is enabled, withAuthHeader will request the JWT token from the tokenProvider and append it to every request // it has interaction with, if source's OIDC service account (source.Status.Auth.ServiceAccountName) and destination's // audience are present. func (c *client) withAuthHeader(ctx context.Context) (context.Context, error) { diff --git a/pkg/adapter/v2/config.go b/pkg/adapter/v2/config.go index 38a9fbb2d39..b8ef74d6c50 100644 --- a/pkg/adapter/v2/config.go +++ b/pkg/adapter/v2/config.go @@ -73,8 +73,8 @@ type EnvConfig struct { // Audience is the audience of the target sink. Audience *string `envconfig:"K_AUDIENCE"` - // Service Account Name is the name of the service account to use for the adapter. - ServiceAccountName *string `envconfig:"K_OIDC_SERVICE_ACCOUNT"` + // OIDCServiceAccount Name is the name of the service account to use for the adapter. + OIDCServiceAccountName *string `envconfig:"K_OIDC_SERVICE_ACCOUNT"` // CACerts are the Certification Authority (CA) certificates in PEM format // according to https://www.rfc-editor.org/rfc/rfc7468. @@ -189,10 +189,10 @@ func (e *EnvConfig) GetSink() string { } func (e *EnvConfig) GetOIDCServiceAccountName() *types.NamespacedName { - if e.ServiceAccountName != nil { + if e.OIDCServiceAccountName != nil { return &types.NamespacedName{ Namespace: e.Namespace, - Name: *e.ServiceAccountName, + Name: *e.OIDCServiceAccountName, } } else { return nil diff --git a/pkg/reconciler/apiserversource/apiserversource.go b/pkg/reconciler/apiserversource/apiserversource.go index 07eae746dbf..65bf864f3c8 100644 --- a/pkg/reconciler/apiserversource/apiserversource.go +++ b/pkg/reconciler/apiserversource/apiserversource.go @@ -369,7 +369,7 @@ func (r *Reconciler) createCloudEventAttributes(src *v1.ApiServerSource) ([]duck // createOIDCRole: this function will call resources package to get the role object // and then pass to kubeclient to make the actual OIDC role func (r *Reconciler) createOIDCRole(ctx context.Context, source *v1.ApiServerSource) error { - roleName := resources.CreateOIDCTokenRoleName(source) + roleName := resources.GetOIDCTokenRoleName(source) //Call kubeclient and see whether the role exist or not role, err := r.roleLister.Roles(source.GetNamespace()).Get(roleName) @@ -411,7 +411,7 @@ func (r *Reconciler) createOIDCRole(ctx context.Context, source *v1.ApiServerSou // createOIDCRoleBinding: this function will call resources package to get the rolebinding object // and then pass to kubeclient to make the actual OIDC rolebinding func (r *Reconciler) createOIDCRoleBinding(ctx context.Context, source *v1.ApiServerSource) error { - roleBindingName := resources.CreateOIDCTokenRoleBindingName(source) + roleBindingName := resources.GetOIDCTokenRoleBindingName(source) // Call kubeclient and see whether the roleBinding exist or not roleBinding, err := r.roleBindingLister.RoleBindings(source.GetNamespace()).Get(roleBindingName) diff --git a/pkg/reconciler/apiserversource/resources/oidc_rolebinding.go b/pkg/reconciler/apiserversource/resources/oidc_rolebinding.go index 616f693cee3..3509be902b3 100644 --- a/pkg/reconciler/apiserversource/resources/oidc_rolebinding.go +++ b/pkg/reconciler/apiserversource/resources/oidc_rolebinding.go @@ -38,7 +38,7 @@ func GetOIDCTokenRoleBindingName(source *v1.ApiServerSource) string { // MakeOIDCRole will return the role object config for generating the JWT token func MakeOIDCRole(source *v1.ApiServerSource) (*rbacv1.Role, error) { - roleName := CreateOIDCTokenRoleName(source) + roleName := GetOIDCTokenRoleName(source) if source.Status.Auth == nil || source.Status.Auth.ServiceAccountName == nil { return nil, fmt.Errorf("Error when making OIDC Role for apiserversource, as the OIDC service account does not exist") @@ -69,8 +69,8 @@ func MakeOIDCRole(source *v1.ApiServerSource) (*rbacv1.Role, error) { // So that ApiServerSource's service account have access to create the JWT token for it's OIDC service account and the target audience // Note: it is in the source.Spec, NOT in source.Auth func MakeOIDCRoleBinding(source *v1.ApiServerSource) (*rbacv1.RoleBinding, error) { - roleName := CreateOIDCTokenRoleName(source) - roleBindingName := CreateOIDCTokenRoleBindingName(source) + roleName := GetOIDCTokenRoleName(source) + roleBindingName := GetOIDCTokenRoleBindingName(source) if source.Spec.ServiceAccountName == "" { return nil, fmt.Errorf("Error when making OIDC RoleBinding for apiserversource, as the Spec service account does not exist") From 277af487a88720ec840180092db5acb3668f5717 Mon Sep 17 00:00:00 2001 From: Leo Li Date: Mon, 11 Dec 2023 08:59:41 -0500 Subject: [PATCH 43/62] Fix the failed unit test by adding the OIDC component, and add the new integration test for role and rolebindng MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Christoph Stäbler --- .../apiserversource/apiserversource.go | 4 +- .../apiserversource/apiserversource_test.go | 184 +++++++++++++++++- .../resources/oidc_rolebinding.go | 14 +- pkg/reconciler/testing/v1/listers.go | 4 + .../kube/informers/rbac/v1/role/fake/fake.go | 40 ++++ vendor/modules.txt | 1 + 6 files changed, 234 insertions(+), 13 deletions(-) create mode 100644 vendor/knative.dev/pkg/client/injection/kube/informers/rbac/v1/role/fake/fake.go diff --git a/pkg/reconciler/apiserversource/apiserversource.go b/pkg/reconciler/apiserversource/apiserversource.go index 65bf864f3c8..4ea8873fbe5 100644 --- a/pkg/reconciler/apiserversource/apiserversource.go +++ b/pkg/reconciler/apiserversource/apiserversource.go @@ -369,7 +369,7 @@ func (r *Reconciler) createCloudEventAttributes(src *v1.ApiServerSource) ([]duck // createOIDCRole: this function will call resources package to get the role object // and then pass to kubeclient to make the actual OIDC role func (r *Reconciler) createOIDCRole(ctx context.Context, source *v1.ApiServerSource) error { - roleName := resources.GetOIDCTokenRoleName(source) + roleName := resources.GetOIDCTokenRoleName(source.Name) //Call kubeclient and see whether the role exist or not role, err := r.roleLister.Roles(source.GetNamespace()).Get(roleName) @@ -411,7 +411,7 @@ func (r *Reconciler) createOIDCRole(ctx context.Context, source *v1.ApiServerSou // createOIDCRoleBinding: this function will call resources package to get the rolebinding object // and then pass to kubeclient to make the actual OIDC rolebinding func (r *Reconciler) createOIDCRoleBinding(ctx context.Context, source *v1.ApiServerSource) error { - roleBindingName := resources.GetOIDCTokenRoleBindingName(source) + roleBindingName := resources.GetOIDCTokenRoleBindingName(source.Name) // Call kubeclient and see whether the roleBinding exist or not roleBinding, err := r.roleBindingLister.RoleBindings(source.GetNamespace()).Get(roleBindingName) diff --git a/pkg/reconciler/apiserversource/apiserversource_test.go b/pkg/reconciler/apiserversource/apiserversource_test.go index f2101a1321e..bad0184bd0e 100644 --- a/pkg/reconciler/apiserversource/apiserversource_test.go +++ b/pkg/reconciler/apiserversource/apiserversource_test.go @@ -19,6 +19,7 @@ package apiserversource import ( "context" "fmt" + rbacv1 "k8s.io/api/rbac/v1" "testing" "github.com/stretchr/testify/require" @@ -53,6 +54,9 @@ import ( rttesting "knative.dev/eventing/pkg/reconciler/testing" rttestingv1 "knative.dev/eventing/pkg/reconciler/testing/v1" . "knative.dev/pkg/reconciler/testing" + + _ "knative.dev/pkg/client/injection/kube/informers/rbac/v1/role/fake" + _ "knative.dev/pkg/client/injection/kube/informers/rbac/v1/rolebinding/fake" ) var ( @@ -83,6 +87,21 @@ var ( Name: &sinkURL.Scheme, URL: sinkURL, } + + sinkAudience = "sink-oidc-audience" + sinkOIDCAddressable = &duckv1.Addressable{ + Name: &sinkURL.Scheme, + URL: sinkURL, + Audience: &sinkAudience, + } + sinkOIDCDest = duckv1.Destination{ + Ref: &duckv1.KReference{ + Name: sinkName, + Kind: "Channel", + APIVersion: "messaging.knative.dev/v1", + }, + Audience: &sinkAudience, + } ) const ( @@ -891,16 +910,18 @@ func TestReconcile(t *testing.T) { APIVersion: "v1", Kind: "Namespace", }}, - SourceSpec: duckv1.SourceSpec{Sink: sinkDest}, + SourceSpec: duckv1.SourceSpec{Sink: sinkOIDCDest}, }), rttestingv1.WithApiServerSourceUID(sourceUID), rttestingv1.WithApiServerSourceObjectMetaGeneration(generation), ), rttestingv1.NewChannel(sinkName, testNS, rttestingv1.WithInitChannelConditions, - rttestingv1.WithChannelAddress(sinkAddressable), + rttestingv1.WithChannelAddress(sinkOIDCAddressable), ), - makeAvailableReceiveAdapter(t), + makeOIDCRole(), + makeOIDCRoleBinding(), + makeAvailableReceiveAdapterWithOIDC(t), }, Key: testNS + "/" + sourceName, WantStatusUpdates: []clientgotesting.UpdateActionImpl{{ @@ -910,7 +931,7 @@ func TestReconcile(t *testing.T) { APIVersion: "v1", Kind: "Namespace", }}, - SourceSpec: duckv1.SourceSpec{Sink: sinkDest}, + SourceSpec: duckv1.SourceSpec{Sink: sinkOIDCDest}, }), rttestingv1.WithApiServerSourceUID(sourceUID), rttestingv1.WithApiServerSourceObjectMetaGeneration(generation), @@ -995,6 +1016,70 @@ func TestReconcile(t *testing.T) { WithReactors: []clientgotesting.ReactionFunc{subjectAccessReviewCreateReactor(true)}, SkipNamespaceValidation: true, // SubjectAccessReview objects are cluster-scoped. }, + { + Name: "OIDC: creates role and rolebinding to create OIDC token", + Ctx: feature.ToContext(context.Background(), feature.Flags{ + feature.OIDCAuthentication: feature.Enabled, + }), + Objects: []runtime.Object{ + rttestingv1.NewApiServerSource(sourceName, testNS, + rttestingv1.WithApiServerSourceSpec(sourcesv1.ApiServerSourceSpec{ + Resources: []sourcesv1.APIVersionKindSelector{{ + APIVersion: "v1", + Kind: "Namespace", + }}, + SourceSpec: duckv1.SourceSpec{Sink: sinkOIDCDest}, + }), + rttestingv1.WithApiServerSourceUID(sourceUID), + rttestingv1.WithApiServerSourceObjectMetaGeneration(generation), + ), + rttestingv1.NewChannel(sinkName, testNS, + rttestingv1.WithInitChannelConditions, + rttestingv1.WithChannelAddress(sinkOIDCAddressable), + ), + makeAvailableReceiveAdapterWithOIDC(t), + makeApiServerSourceOIDCServiceAccount(), + }, + Key: testNS + "/" + sourceName, + WantStatusUpdates: []clientgotesting.UpdateActionImpl{{ + Object: rttestingv1.NewApiServerSource(sourceName, testNS, + rttestingv1.WithApiServerSourceSpec(sourcesv1.ApiServerSourceSpec{ + Resources: []sourcesv1.APIVersionKindSelector{{ + APIVersion: "v1", + Kind: "Namespace", + }}, + SourceSpec: duckv1.SourceSpec{Sink: sinkOIDCDest}, + }), + rttestingv1.WithApiServerSourceUID(sourceUID), + rttestingv1.WithApiServerSourceObjectMetaGeneration(generation), + // Status Update: + rttestingv1.WithInitApiServerSourceConditions, + rttestingv1.WithApiServerSourceDeployed, + rttestingv1.WithApiServerSourceSink(sinkURI), + rttestingv1.WithApiServerSourceSufficientPermissions, + rttestingv1.WithApiServerSourceReferenceModeEventTypes(source), + rttestingv1.WithApiServerSourceStatusObservedGeneration(generation), + rttestingv1.WithApiServerSourceStatusNamespaces([]string{testNS}), + rttestingv1.WithApiServerSourceOIDCIdentityCreatedSucceeded(), + rttestingv1.WithApiServerSourceOIDCServiceAccountName(makeApiServerSourceOIDCServiceAccount().Name), + ), + }}, + WantCreates: []runtime.Object{ + makeOIDCRole(), + makeOIDCRoleBinding(), + makeSubjectAccessReview("namespaces", "get", "default"), + makeSubjectAccessReview("namespaces", "list", "default"), + makeSubjectAccessReview("namespaces", "watch", "default"), + }, + WantEvents: []string{ + Eventf(corev1.EventTypeNormal, "FinalizerUpdate", "Updated %q finalizers", sourceName), + }, + WantPatches: []clientgotesting.PatchActionImpl{ + patchFinalizers(sourceName, testNS), + }, + WithReactors: []clientgotesting.ReactionFunc{subjectAccessReviewCreateReactor(true)}, + SkipNamespaceValidation: true, // SubjectAccessReview objects are cluster-scoped. + }, } logger := logtesting.TestLogger(t) @@ -1008,6 +1093,8 @@ func TestReconcile(t *testing.T) { configs: &reconcilersource.EmptyVarsGenerator{}, namespaceLister: listers.GetNamespaceLister(), serviceAccountLister: listers.GetServiceAccountLister(), + roleBindingLister: listers.GetRoleBindingLister(), + roleLister: listers.GetRoleLister(), } return apiserversource.NewReconciler(ctx, logger, fakeeventingclient.Get(ctx), listers.GetApiServerSourceLister(), @@ -1055,6 +1142,50 @@ func makeReceiveAdapterWithName(t *testing.T, sourceName string) *appsv1.Deploym return ra } +func makeReceiveAdapterWithOIDC(t *testing.T) *appsv1.Deployment { + t.Helper() + + src := rttestingv1.NewApiServerSource(sourceName, testNS, + rttestingv1.WithApiServerSourceSpec(sourcesv1.ApiServerSourceSpec{ + Resources: []sourcesv1.APIVersionKindSelector{{ + APIVersion: "v1", + Kind: "Namespace", + }}, + SourceSpec: duckv1.SourceSpec{ + Sink: sinkOIDCDest, + }, + }), + rttestingv1.WithApiServerSourceUID(sourceUID), + // Status Update: + rttestingv1.WithInitApiServerSourceConditions, + rttestingv1.WithApiServerSourceDeployed, + rttestingv1.WithApiServerSourceSink(sinkURI), + rttestingv1.WithApiServerSourceOIDCServiceAccountName(makeApiServerSourceOIDCServiceAccount().Name), + ) + + args := resources.ReceiveAdapterArgs{ + Image: image, + Source: src, + Labels: resources.Labels(sourceName), + SinkURI: sinkURI.String(), + Configs: &reconcilersource.EmptyVarsGenerator{}, + Namespaces: []string{testNS}, + Audience: &sinkAudience, + } + + ra, err := resources.MakeReceiveAdapter(&args) + require.NoError(t, err) + + return ra +} + +func makeAvailableReceiveAdapterWithOIDC(t *testing.T) *appsv1.Deployment { + ra := makeReceiveAdapterWithOIDC(t) + rttesting.WithDeploymentAvailable()(ra) + + return ra +} + func makeAvailableReceiveAdapter(t *testing.T) *appsv1.Deployment { ra := makeReceiveAdapter(t) rttesting.WithDeploymentAvailable()(ra) @@ -1204,6 +1335,51 @@ func makeSubjectAccessReview(resource, verb, sa string) *authorizationv1.Subject return makeNamespacedSubjectAccessReview(resource, verb, sa, testNS) } +func makeOIDCRole() *rbacv1.Role { + return &rbacv1.Role{ + ObjectMeta: metav1.ObjectMeta{ + Name: resources.GetOIDCTokenRoleName(sourceName), + Namespace: testNS, + Annotations: map[string]string{ + "description": fmt.Sprintf("Role for OIDC Authentication for ApiServerSource %q", sourceName), + }, + }, + Rules: []rbacv1.PolicyRule{ + { + APIGroups: []string{""}, + // apiServerSource OIDC service account name, it is in the source.Status, NOT in source.Spec + ResourceNames: []string{makeApiServerSourceOIDCServiceAccount().Name}, + Resources: []string{"serviceaccounts/token"}, + Verbs: []string{"create"}, + }, + }, + } +} + +func makeOIDCRoleBinding() *rbacv1.RoleBinding { + return &rbacv1.RoleBinding{ + ObjectMeta: metav1.ObjectMeta{ + Name: resources.GetOIDCTokenRoleBindingName(sourceName), + Namespace: testNS, + Annotations: map[string]string{ + "description": fmt.Sprintf("Role Binding for OIDC Authentication for ApiServerSource %q", sourceName), + }, + }, + RoleRef: rbacv1.RoleRef{ + APIGroup: "rbac.authorization.k8s.io", + Kind: "Role", + Name: resources.GetOIDCTokenRoleName(sourceName), + }, + Subjects: []rbacv1.Subject{ + { + Kind: "ServiceAccount", + Namespace: testNS, + Name: "default", + }, + }, + } +} + func subjectAccessReviewCreateReactor(allowed bool) clientgotesting.ReactionFunc { return func(action clientgotesting.Action) (handled bool, ret runtime.Object, err error) { if action.GetVerb() == "create" && action.GetResource().Resource == "subjectaccessreviews" { diff --git a/pkg/reconciler/apiserversource/resources/oidc_rolebinding.go b/pkg/reconciler/apiserversource/resources/oidc_rolebinding.go index 3509be902b3..8929c9667a8 100644 --- a/pkg/reconciler/apiserversource/resources/oidc_rolebinding.go +++ b/pkg/reconciler/apiserversource/resources/oidc_rolebinding.go @@ -27,18 +27,18 @@ import ( ) // GetOIDCTokenRoleName will return the name of the role for creating the JWT token -func GetOIDCTokenRoleName(source *v1.ApiServerSource) string { - return kmeta.ChildName(source.GetName(), "create-oidc-token-role") +func GetOIDCTokenRoleName(sourceName string) string { + return kmeta.ChildName(sourceName, "create-oidc-token-role") } // GetOIDCTokenRoleBindingName will return the name of the rolebinding for creating the JWT token -func GetOIDCTokenRoleBindingName(source *v1.ApiServerSource) string { - return kmeta.ChildName(source.GetName(), "create-oidc-token-rolebinding") +func GetOIDCTokenRoleBindingName(sourceName string) string { + return kmeta.ChildName(sourceName, "create-oidc-token-rolebinding") } // MakeOIDCRole will return the role object config for generating the JWT token func MakeOIDCRole(source *v1.ApiServerSource) (*rbacv1.Role, error) { - roleName := GetOIDCTokenRoleName(source) + roleName := GetOIDCTokenRoleName(source.Name) if source.Status.Auth == nil || source.Status.Auth.ServiceAccountName == nil { return nil, fmt.Errorf("Error when making OIDC Role for apiserversource, as the OIDC service account does not exist") @@ -69,8 +69,8 @@ func MakeOIDCRole(source *v1.ApiServerSource) (*rbacv1.Role, error) { // So that ApiServerSource's service account have access to create the JWT token for it's OIDC service account and the target audience // Note: it is in the source.Spec, NOT in source.Auth func MakeOIDCRoleBinding(source *v1.ApiServerSource) (*rbacv1.RoleBinding, error) { - roleName := GetOIDCTokenRoleName(source) - roleBindingName := GetOIDCTokenRoleBindingName(source) + roleName := GetOIDCTokenRoleName(source.Name) + roleBindingName := GetOIDCTokenRoleBindingName(source.Name) if source.Spec.ServiceAccountName == "" { return nil, fmt.Errorf("Error when making OIDC RoleBinding for apiserversource, as the Spec service account does not exist") diff --git a/pkg/reconciler/testing/v1/listers.go b/pkg/reconciler/testing/v1/listers.go index 83f1b599893..788b2fab2cc 100644 --- a/pkg/reconciler/testing/v1/listers.go +++ b/pkg/reconciler/testing/v1/listers.go @@ -180,6 +180,10 @@ func (l *Listers) GetServiceLister() corev1listers.ServiceLister { return corev1listers.NewServiceLister(l.indexerFor(&corev1.Service{})) } +func (l *Listers) GetRoleLister() rbacv1listers.RoleLister { + return rbacv1listers.NewRoleLister(l.indexerFor(&rbacv1.Role{})) +} + func (l *Listers) GetRoleBindingLister() rbacv1listers.RoleBindingLister { return rbacv1listers.NewRoleBindingLister(l.indexerFor(&rbacv1.RoleBinding{})) } diff --git a/vendor/knative.dev/pkg/client/injection/kube/informers/rbac/v1/role/fake/fake.go b/vendor/knative.dev/pkg/client/injection/kube/informers/rbac/v1/role/fake/fake.go new file mode 100644 index 00000000000..e93f76659e2 --- /dev/null +++ b/vendor/knative.dev/pkg/client/injection/kube/informers/rbac/v1/role/fake/fake.go @@ -0,0 +1,40 @@ +/* +Copyright 2022 The Knative Authors + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +// Code generated by injection-gen. DO NOT EDIT. + +package fake + +import ( + context "context" + + fake "knative.dev/pkg/client/injection/kube/informers/factory/fake" + role "knative.dev/pkg/client/injection/kube/informers/rbac/v1/role" + controller "knative.dev/pkg/controller" + injection "knative.dev/pkg/injection" +) + +var Get = role.Get + +func init() { + injection.Fake.RegisterInformer(withInformer) +} + +func withInformer(ctx context.Context) (context.Context, controller.Informer) { + f := fake.Get(ctx) + inf := f.Rbac().V1().Roles() + return context.WithValue(ctx, role.Key{}, inf), inf.Informer() +} diff --git a/vendor/modules.txt b/vendor/modules.txt index 35f85b864b0..78f67e92c40 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -1264,6 +1264,7 @@ knative.dev/pkg/client/injection/kube/informers/core/v1/serviceaccount/fake knative.dev/pkg/client/injection/kube/informers/factory knative.dev/pkg/client/injection/kube/informers/factory/fake knative.dev/pkg/client/injection/kube/informers/rbac/v1/role +knative.dev/pkg/client/injection/kube/informers/rbac/v1/role/fake knative.dev/pkg/client/injection/kube/informers/rbac/v1/rolebinding knative.dev/pkg/client/injection/kube/informers/rbac/v1/rolebinding/fake knative.dev/pkg/client/injection/kube/reconciler/core/v1/namespace From c1248ea19715008a72dbd214b7bc4594e7ad151e Mon Sep 17 00:00:00 2001 From: Leo Li Date: Mon, 11 Dec 2023 11:14:58 -0500 Subject: [PATCH 44/62] Pass in the fake kubeclinet to apiserversource Signed-off-by: Leo Li --- config/core/resources/apiserversource.yaml | 3 +++ pkg/adapter/v2/main_test.go | 10 ++++++++-- pkg/apis/sources/v1/apiserver_lifecycle.go | 1 + 3 files changed, 12 insertions(+), 2 deletions(-) diff --git a/config/core/resources/apiserversource.yaml b/config/core/resources/apiserversource.yaml index e46c17ec32c..27f454460da 100644 --- a/config/core/resources/apiserversource.yaml +++ b/config/core/resources/apiserversource.yaml @@ -249,6 +249,9 @@ spec: sinkCACerts: description: CACerts is the Certification Authority (CA) certificates in PEM format that the source trusts when sending events to the sink. type: string + sinkAudience: + description: Audience is the OIDC audience of the sink. This only needs to be set if the target is not an Addressable and thus the Audience can't be received from the Addressable itself. If the target is an Addressable and specifies an Audience, the target's Audience takes precedence. + type: string namespaces: description: Namespaces show the namespaces currently watched by the ApiServerSource type: array diff --git a/pkg/adapter/v2/main_test.go b/pkg/adapter/v2/main_test.go index 25394074ab1..de2130f003e 100644 --- a/pkg/adapter/v2/main_test.go +++ b/pkg/adapter/v2/main_test.go @@ -28,6 +28,7 @@ import ( metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/types" + fakekubeclient "knative.dev/pkg/client/injection/kube/client/fake" kubeclient "knative.dev/pkg/client/injection/kube/client/fake" "knative.dev/pkg/configmap" "knative.dev/pkg/leaderelection" @@ -50,7 +51,7 @@ type myAdapter struct { blocking bool } -func TestMainWithNothing(t *testing.T) { +func TestMainWithContext(t *testing.T) { os.Setenv("K_SINK", "http://sink") os.Setenv("NAMESPACE", "ns") os.Setenv("K_METRICS_CONFIG", "error config") @@ -65,7 +66,10 @@ func TestMainWithNothing(t *testing.T) { os.Unsetenv("MODE") }() - Main("mycomponent", + ctx := context.TODO() + ctx, _ = fakekubeclient.With(ctx) + + MainWithContext(ctx, "mycomponent", func() EnvConfigAccessor { return &myEnvConfig{} }, func(ctx context.Context, processed EnvConfigAccessor, client cloudevents.Client) Adapter { env := processed.(*myEnvConfig) @@ -103,6 +107,7 @@ func TestMainWithInformerNoLeaderElection(t *testing.T) { }() ctx, cancel := context.WithCancel(context.TODO()) + ctx, _ = fakekubeclient.With(ctx) env := ConstructEnvOrDie(func() EnvConfigAccessor { return &myEnvConfig{} }) done := make(chan bool) go func() { @@ -161,6 +166,7 @@ func TestMain_MetricsConfig(t *testing.T) { }() ctx, cancel := context.WithCancel(context.TODO()) + ctx, _ = fakekubeclient.With(ctx) env := ConstructEnvOrDie(func() EnvConfigAccessor { return &myEnvConfig{} }) done := make(chan bool) go func() { diff --git a/pkg/apis/sources/v1/apiserver_lifecycle.go b/pkg/apis/sources/v1/apiserver_lifecycle.go index 70d0f767493..b4604dfe432 100644 --- a/pkg/apis/sources/v1/apiserver_lifecycle.go +++ b/pkg/apis/sources/v1/apiserver_lifecycle.go @@ -84,6 +84,7 @@ func (s *ApiServerSourceStatus) MarkSink(addr *duckv1.Addressable) { if addr != nil { s.SinkURI = addr.URL s.SinkCACerts = addr.CACerts + s.SinkAudience = addr.Audience apiserverCondSet.Manage(s).MarkTrue(ApiServerConditionSinkProvided) } else { apiserverCondSet.Manage(s).MarkFalse(ApiServerConditionSinkProvided, "SinkEmpty", "Sink has resolved to empty.%s", "") From da14390d477d0cca25f0f2659cbd403641245aa2 Mon Sep 17 00:00:00 2001 From: Leo Li Date: Mon, 11 Dec 2023 11:16:20 -0500 Subject: [PATCH 45/62] Apply suggestions from code review MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Christoph Stäbler --- pkg/adapter/v2/cloudevents.go | 2 +- pkg/adapter/v2/config.go | 3 +-- pkg/reconciler/apiserversource/apiserversource.go | 2 -- 3 files changed, 2 insertions(+), 5 deletions(-) diff --git a/pkg/adapter/v2/cloudevents.go b/pkg/adapter/v2/cloudevents.go index 2efdeac0490..b3212ef7179 100644 --- a/pkg/adapter/v2/cloudevents.go +++ b/pkg/adapter/v2/cloudevents.go @@ -236,7 +236,7 @@ type client struct { oidcTokenProvider *auth.OIDCTokenProvider audience *string - serviceAccountName *types.NamespacedName + oidcServiceAccountName *types.NamespacedName } func (c *client) CloseIdleConnections() { diff --git a/pkg/adapter/v2/config.go b/pkg/adapter/v2/config.go index b8ef74d6c50..27a4a1eea3c 100644 --- a/pkg/adapter/v2/config.go +++ b/pkg/adapter/v2/config.go @@ -194,9 +194,8 @@ func (e *EnvConfig) GetOIDCServiceAccountName() *types.NamespacedName { Namespace: e.Namespace, Name: *e.OIDCServiceAccountName, } - } else { - return nil } + return nil } func (e *EnvConfig) GetCACerts() *string { diff --git a/pkg/reconciler/apiserversource/apiserversource.go b/pkg/reconciler/apiserversource/apiserversource.go index 4ea8873fbe5..5e35f424754 100644 --- a/pkg/reconciler/apiserversource/apiserversource.go +++ b/pkg/reconciler/apiserversource/apiserversource.go @@ -387,7 +387,6 @@ func (r *Reconciler) createOIDCRole(ctx context.Context, source *v1.ApiServerSou if err != nil { return fmt.Errorf("could not create OIDC service account role %s/%s for %s: %w", source.GetName(), source.GetNamespace(), "ApiServerSource", err) } - } else { // If the role does exist, we will check whether an update is needed // By comparing the role's rule @@ -428,7 +427,6 @@ func (r *Reconciler) createOIDCRoleBinding(ctx context.Context, source *v1.ApiSe if err != nil { return fmt.Errorf("could not create OIDC service account rolebinding %s/%s for %s: %w", source.GetName(), source.GetNamespace(), "apiserversource", err) } - } else { // If the role does exist, we will check whether an update is needed // By comparing the role's rule From 3f0265db9aeba203b59cd5cfb9e731fe6c547041 Mon Sep 17 00:00:00 2001 From: Leo Li Date: Mon, 11 Dec 2023 11:17:39 -0500 Subject: [PATCH 46/62] nit fix Signed-off-by: Leo Li --- pkg/adapter/v2/cloudevents.go | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/pkg/adapter/v2/cloudevents.go b/pkg/adapter/v2/cloudevents.go index b3212ef7179..4bad59436b4 100644 --- a/pkg/adapter/v2/cloudevents.go +++ b/pkg/adapter/v2/cloudevents.go @@ -208,7 +208,7 @@ func NewClient(cfg ClientConfig) (Client, error) { if cfg.Env != nil { client.audience = cfg.Env.GetAudience() - client.serviceAccountName = cfg.Env.GetOIDCServiceAccountName() + client.oidcServiceAccountName = cfg.Env.GetOIDCServiceAccountName() } return client, nil @@ -234,8 +234,8 @@ type client struct { crStatusEventClient *crstatusevent.CRStatusEventClient closeIdler closeIdler - oidcTokenProvider *auth.OIDCTokenProvider - audience *string + oidcTokenProvider *auth.OIDCTokenProvider + audience *string oidcServiceAccountName *types.NamespacedName } @@ -250,7 +250,7 @@ func (c *client) Send(ctx context.Context, out event.Event) protocol.Result { c.applyOverrides(&out) var err error - if c.audience != nil && c.serviceAccountName != nil { + if c.audience != nil && c.oidcServiceAccountName != nil { ctx, err = c.withAuthHeader(ctx) if err != nil { return err @@ -267,7 +267,7 @@ func (c *client) Request(ctx context.Context, out event.Event) (*event.Event, pr c.applyOverrides(&out) var err error - if c.audience != nil && c.serviceAccountName != nil { + if c.audience != nil && c.oidcServiceAccountName != nil { ctx, err = c.withAuthHeader(ctx) if err != nil { return nil, err @@ -405,7 +405,7 @@ func tracecontextMiddleware(h nethttp.Handler) nethttp.Handler { // audience are present. func (c *client) withAuthHeader(ctx context.Context) (context.Context, error) { // Request the JWT token for the given service account - jwt, err := c.oidcTokenProvider.GetJWT(*c.serviceAccountName, *c.audience) + jwt, err := c.oidcTokenProvider.GetJWT(*c.oidcServiceAccountName, *c.audience) if err != nil { return ctx, protocol.NewResult("Failed when appending the Authorization header to the outgoing request %w", err) } From d599e6430154a560ad83008ccf95e8010d278fcd Mon Sep 17 00:00:00 2001 From: Leo Li Date: Mon, 11 Dec 2023 11:18:40 -0500 Subject: [PATCH 47/62] nit fix Signed-off-by: Leo Li --- pkg/reconciler/apiserversource/resources/oidc_rolebinding.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkg/reconciler/apiserversource/resources/oidc_rolebinding.go b/pkg/reconciler/apiserversource/resources/oidc_rolebinding.go index 8929c9667a8..bf41deb8ee7 100644 --- a/pkg/reconciler/apiserversource/resources/oidc_rolebinding.go +++ b/pkg/reconciler/apiserversource/resources/oidc_rolebinding.go @@ -28,12 +28,12 @@ import ( // GetOIDCTokenRoleName will return the name of the role for creating the JWT token func GetOIDCTokenRoleName(sourceName string) string { - return kmeta.ChildName(sourceName, "create-oidc-token-role") + return kmeta.ChildName(sourceName, "create-oidc-token") } // GetOIDCTokenRoleBindingName will return the name of the rolebinding for creating the JWT token func GetOIDCTokenRoleBindingName(sourceName string) string { - return kmeta.ChildName(sourceName, "create-oidc-token-rolebinding") + return kmeta.ChildName(sourceName, "create-oidc-token") } // MakeOIDCRole will return the role object config for generating the JWT token From d0b400efb6109f25a2cf968d0ebf98fa8e1e4953 Mon Sep 17 00:00:00 2001 From: Leo Li Date: Mon, 11 Dec 2023 12:11:33 -0500 Subject: [PATCH 48/62] Fix the failed unit test: no audience is passed in Signed-off-by: Leo Li --- pkg/reconciler/apiserversource/apiserversource_test.go | 7 ++++--- pkg/reconciler/testing/v1/apiserversouce.go | 6 ++++++ 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/pkg/reconciler/apiserversource/apiserversource_test.go b/pkg/reconciler/apiserversource/apiserversource_test.go index bad0184bd0e..f50da246dcc 100644 --- a/pkg/reconciler/apiserversource/apiserversource_test.go +++ b/pkg/reconciler/apiserversource/apiserversource_test.go @@ -19,9 +19,10 @@ package apiserversource import ( "context" "fmt" - rbacv1 "k8s.io/api/rbac/v1" "testing" + rbacv1 "k8s.io/api/rbac/v1" + "github.com/stretchr/testify/require" appsv1 "k8s.io/api/apps/v1" @@ -938,7 +939,7 @@ func TestReconcile(t *testing.T) { // Status Update: rttestingv1.WithInitApiServerSourceConditions, rttestingv1.WithApiServerSourceDeployed, - rttestingv1.WithApiServerSourceSink(sinkURI), + rttestingv1.WithApiServerSourceSinkAddressable(sinkOIDCAddressable), rttestingv1.WithApiServerSourceSufficientPermissions, rttestingv1.WithApiServerSourceReferenceModeEventTypes(source), rttestingv1.WithApiServerSourceStatusObservedGeneration(generation), @@ -1055,7 +1056,7 @@ func TestReconcile(t *testing.T) { // Status Update: rttestingv1.WithInitApiServerSourceConditions, rttestingv1.WithApiServerSourceDeployed, - rttestingv1.WithApiServerSourceSink(sinkURI), + rttestingv1.WithApiServerSourceSinkAddressable(sinkOIDCAddressable), rttestingv1.WithApiServerSourceSufficientPermissions, rttestingv1.WithApiServerSourceReferenceModeEventTypes(source), rttestingv1.WithApiServerSourceStatusObservedGeneration(generation), diff --git a/pkg/reconciler/testing/v1/apiserversouce.go b/pkg/reconciler/testing/v1/apiserversouce.go index 08d799de74c..cdbe78c8b81 100644 --- a/pkg/reconciler/testing/v1/apiserversouce.go +++ b/pkg/reconciler/testing/v1/apiserversouce.go @@ -72,6 +72,12 @@ func WithApiServerSourceSink(uri *apis.URL) ApiServerSourceOption { } } +func WithApiServerSourceSinkAddressable(sinkAddr *duckv1.Addressable) ApiServerSourceOption { + return func(s *v1.ApiServerSource) { + s.Status.MarkSink(sinkAddr) + } +} + func WithApiServerSourceDeploymentUnavailable(s *v1.ApiServerSource) { // The Deployment uses GenerateName, so its name is empty. name := kmeta.ChildName(fmt.Sprintf("apiserversource-%s-", s.Name), string(s.GetUID())) From f67e9065fd8de3beb82ec60752e9a287067f44d8 Mon Sep 17 00:00:00 2001 From: Leo Li Date: Mon, 11 Dec 2023 13:37:23 -0500 Subject: [PATCH 49/62] nit: boilerplate format Signed-off-by: Leo Li --- pkg/reconciler/apiserversource/resources/oidc_rolebinding.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkg/reconciler/apiserversource/resources/oidc_rolebinding.go b/pkg/reconciler/apiserversource/resources/oidc_rolebinding.go index bf41deb8ee7..507deb4fe21 100644 --- a/pkg/reconciler/apiserversource/resources/oidc_rolebinding.go +++ b/pkg/reconciler/apiserversource/resources/oidc_rolebinding.go @@ -5,7 +5,7 @@ Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at - http://www.apache.org/licenses/LICENSE-2.0 + http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, From bf4c72748624206b9dec263bcd5b7e1691e910d1 Mon Sep 17 00:00:00 2001 From: Leo Li Date: Tue, 12 Dec 2023 11:44:20 -0500 Subject: [PATCH 50/62] Change the comment and re-order the code according to the review comment Signed-off-by: Leo Li --- .../apiserversource/apiserversource.go | 23 +++++++++---------- 1 file changed, 11 insertions(+), 12 deletions(-) diff --git a/pkg/reconciler/apiserversource/apiserversource.go b/pkg/reconciler/apiserversource/apiserversource.go index 5e35f424754..a865d3e232a 100644 --- a/pkg/reconciler/apiserversource/apiserversource.go +++ b/pkg/reconciler/apiserversource/apiserversource.go @@ -371,15 +371,15 @@ func (r *Reconciler) createCloudEventAttributes(src *v1.ApiServerSource) ([]duck func (r *Reconciler) createOIDCRole(ctx context.Context, source *v1.ApiServerSource) error { roleName := resources.GetOIDCTokenRoleName(source.Name) - //Call kubeclient and see whether the role exist or not - role, err := r.roleLister.Roles(source.GetNamespace()).Get(roleName) - - expected, errMakeRole := resources.MakeOIDCRole(source) + expected, err := resources.MakeOIDCRole(source) - if errMakeRole != nil { - return fmt.Errorf("Cannot create OIDC role for ApiServerSource %s/%s: %w", source.GetName(), source.GetNamespace(), errMakeRole) + if err != nil { + return fmt.Errorf("Cannot create OIDC role for ApiServerSource %s/%s: %w", source.GetName(), source.GetNamespace(), err) } + // By querying roleLister to see whether the role exist or not + role, err := r.roleLister.Roles(source.GetNamespace()).Get(roleName) + if apierrs.IsNotFound(err) { // If the role does not exist, we will call kubeclient to create it role = expected @@ -412,14 +412,13 @@ func (r *Reconciler) createOIDCRole(ctx context.Context, source *v1.ApiServerSou func (r *Reconciler) createOIDCRoleBinding(ctx context.Context, source *v1.ApiServerSource) error { roleBindingName := resources.GetOIDCTokenRoleBindingName(source.Name) - // Call kubeclient and see whether the roleBinding exist or not - roleBinding, err := r.roleBindingLister.RoleBindings(source.GetNamespace()).Get(roleBindingName) - expected, errMakeRoleBinding := resources.MakeOIDCRoleBinding(source) - - if errMakeRoleBinding != nil { - return fmt.Errorf("Cannot create OIDC roleBinding for ApiServerSource %s/%s: %w", source.GetName(), source.GetNamespace(), errMakeRoleBinding) + expected, err := resources.MakeOIDCRoleBinding(source) + if err != nil { + return fmt.Errorf("Cannot create OIDC roleBinding for ApiServerSource %s/%s: %w", source.GetName(), source.GetNamespace(), err) } + // By querying roleBindingLister to see whether the roleBinding exist or not + roleBinding, err := r.roleBindingLister.RoleBindings(source.GetNamespace()).Get(roleBindingName) if apierrs.IsNotFound(err) { // If the role does not exist, we will call kubeclient to create it roleBinding = expected From 479aa7f1b67b0074b2836a7999005d1b167836d3 Mon Sep 17 00:00:00 2001 From: Leo Li Date: Wed, 13 Dec 2023 16:36:10 -0500 Subject: [PATCH 51/62] Change to use the filtered informer, and add the informer eventhandler for the role and rolebinding informers Signed-off-by: Leo Li --- pkg/reconciler/apiserversource/controller.go | 20 ++++- .../resources/oidc_rolebinding.go | 6 ++ .../factory/filtered/filtered_factory.go | 78 +++++++++++++++++++ .../informers/rbac/v1/role/filtered/role.go | 65 ++++++++++++++++ .../v1/rolebinding/filtered/rolebinding.go | 65 ++++++++++++++++ vendor/modules.txt | 3 + 6 files changed, 233 insertions(+), 4 deletions(-) create mode 100644 vendor/knative.dev/pkg/client/injection/kube/informers/factory/filtered/filtered_factory.go create mode 100644 vendor/knative.dev/pkg/client/injection/kube/informers/rbac/v1/role/filtered/role.go create mode 100644 vendor/knative.dev/pkg/client/injection/kube/informers/rbac/v1/rolebinding/filtered/rolebinding.go diff --git a/pkg/reconciler/apiserversource/controller.go b/pkg/reconciler/apiserversource/controller.go index 3685f387c56..7de60dfe042 100644 --- a/pkg/reconciler/apiserversource/controller.go +++ b/pkg/reconciler/apiserversource/controller.go @@ -38,8 +38,8 @@ import ( apiserversourceinformer "knative.dev/eventing/pkg/client/injection/informers/sources/v1/apiserversource" apiserversourcereconciler "knative.dev/eventing/pkg/client/injection/reconciler/sources/v1/apiserversource" serviceaccountinformer "knative.dev/pkg/client/injection/kube/informers/core/v1/serviceaccount" - roleinformer "knative.dev/pkg/client/injection/kube/informers/rbac/v1/role" - rolebindinginformer "knative.dev/pkg/client/injection/kube/informers/rbac/v1/rolebinding" + roleinformer "knative.dev/pkg/client/injection/kube/informers/rbac/v1/role/filtered" + rolebindinginformer "knative.dev/pkg/client/injection/kube/informers/rbac/v1/rolebinding/filtered" ) // envConfig will be used to extract the required environment variables using @@ -61,8 +61,10 @@ func NewController( namespaceInformer := namespace.Get(ctx) serviceaccountInformer := serviceaccountinformer.Get(ctx) - roleInformer := roleinformer.Get(ctx) - rolebindingInformer := rolebindinginformer.Get(ctx) + // Create a selector string + selectorString := "role=oidc-token-creator" + roleInformer := roleinformer.Get(ctx, selectorString) + rolebindingInformer := rolebindinginformer.Get(ctx, selectorString) var globalResync func(obj interface{}) @@ -108,6 +110,16 @@ func NewController( Handler: controller.HandleAll(impl.EnqueueControllerOf), }) + roleInformer.Informer().AddEventHandler(cache.FilteringResourceEventHandler{ + FilterFunc: controller.FilterController(&v1.ApiServerSource{}), + Handler: controller.HandleAll(impl.EnqueueControllerOf), + }) + + rolebindingInformer.Informer().AddEventHandler(cache.FilteringResourceEventHandler{ + FilterFunc: controller.FilterController(&v1.ApiServerSource{}), + Handler: controller.HandleAll(impl.EnqueueControllerOf), + }) + cb := func() { logging.FromContext(ctx).Info("Global resync of APIServerSources due to namespaces changing.") impl.GlobalResync(apiServerSourceInformer.Informer()) diff --git a/pkg/reconciler/apiserversource/resources/oidc_rolebinding.go b/pkg/reconciler/apiserversource/resources/oidc_rolebinding.go index 507deb4fe21..64625c9d2c0 100644 --- a/pkg/reconciler/apiserversource/resources/oidc_rolebinding.go +++ b/pkg/reconciler/apiserversource/resources/oidc_rolebinding.go @@ -51,6 +51,9 @@ func MakeOIDCRole(source *v1.ApiServerSource) (*rbacv1.Role, error) { Annotations: map[string]string{ "description": fmt.Sprintf("Role for OIDC Authentication for ApiServerSource %q", source.GetName()), }, + Labels: map[string]string{ + "role": "oidc-token-creator", + }, }, Rules: []rbacv1.PolicyRule{ rbacv1.PolicyRule{ @@ -83,6 +86,9 @@ func MakeOIDCRoleBinding(source *v1.ApiServerSource) (*rbacv1.RoleBinding, error Annotations: map[string]string{ "description": fmt.Sprintf("Role Binding for OIDC Authentication for ApiServerSource %q", source.GetName()), }, + Labels: map[string]string{ + "role": "oidc-token-creator", + }, }, RoleRef: rbacv1.RoleRef{ APIGroup: "rbac.authorization.k8s.io", diff --git a/vendor/knative.dev/pkg/client/injection/kube/informers/factory/filtered/filtered_factory.go b/vendor/knative.dev/pkg/client/injection/kube/informers/factory/filtered/filtered_factory.go new file mode 100644 index 00000000000..621a2005373 --- /dev/null +++ b/vendor/knative.dev/pkg/client/injection/kube/informers/factory/filtered/filtered_factory.go @@ -0,0 +1,78 @@ +/* +Copyright 2022 The Knative Authors + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +// Code generated by injection-gen. DO NOT EDIT. + +package filteredFactory + +import ( + context "context" + + v1 "k8s.io/apimachinery/pkg/apis/meta/v1" + informers "k8s.io/client-go/informers" + client "knative.dev/pkg/client/injection/kube/client" + controller "knative.dev/pkg/controller" + injection "knative.dev/pkg/injection" + logging "knative.dev/pkg/logging" +) + +func init() { + injection.Default.RegisterInformerFactory(withInformerFactory) +} + +// Key is used as the key for associating information with a context.Context. +type Key struct { + Selector string +} + +type LabelKey struct{} + +func WithSelectors(ctx context.Context, selector ...string) context.Context { + return context.WithValue(ctx, LabelKey{}, selector) +} + +func withInformerFactory(ctx context.Context) context.Context { + c := client.Get(ctx) + untyped := ctx.Value(LabelKey{}) + if untyped == nil { + logging.FromContext(ctx).Panic( + "Unable to fetch labelkey from context.") + } + labelSelectors := untyped.([]string) + for _, selector := range labelSelectors { + selectorVal := selector + opts := []informers.SharedInformerOption{} + if injection.HasNamespaceScope(ctx) { + opts = append(opts, informers.WithNamespace(injection.GetNamespaceScope(ctx))) + } + opts = append(opts, informers.WithTweakListOptions(func(l *v1.ListOptions) { + l.LabelSelector = selectorVal + })) + ctx = context.WithValue(ctx, Key{Selector: selectorVal}, + informers.NewSharedInformerFactoryWithOptions(c, controller.GetResyncPeriod(ctx), opts...)) + } + return ctx +} + +// Get extracts the InformerFactory from the context. +func Get(ctx context.Context, selector string) informers.SharedInformerFactory { + untyped := ctx.Value(Key{Selector: selector}) + if untyped == nil { + logging.FromContext(ctx).Panicf( + "Unable to fetch k8s.io/client-go/informers.SharedInformerFactory with selector %s from context.", selector) + } + return untyped.(informers.SharedInformerFactory) +} diff --git a/vendor/knative.dev/pkg/client/injection/kube/informers/rbac/v1/role/filtered/role.go b/vendor/knative.dev/pkg/client/injection/kube/informers/rbac/v1/role/filtered/role.go new file mode 100644 index 00000000000..701bb09625f --- /dev/null +++ b/vendor/knative.dev/pkg/client/injection/kube/informers/rbac/v1/role/filtered/role.go @@ -0,0 +1,65 @@ +/* +Copyright 2022 The Knative Authors + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +// Code generated by injection-gen. DO NOT EDIT. + +package filtered + +import ( + context "context" + + v1 "k8s.io/client-go/informers/rbac/v1" + filtered "knative.dev/pkg/client/injection/kube/informers/factory/filtered" + controller "knative.dev/pkg/controller" + injection "knative.dev/pkg/injection" + logging "knative.dev/pkg/logging" +) + +func init() { + injection.Default.RegisterFilteredInformers(withInformer) +} + +// Key is used for associating the Informer inside the context.Context. +type Key struct { + Selector string +} + +func withInformer(ctx context.Context) (context.Context, []controller.Informer) { + untyped := ctx.Value(filtered.LabelKey{}) + if untyped == nil { + logging.FromContext(ctx).Panic( + "Unable to fetch labelkey from context.") + } + labelSelectors := untyped.([]string) + infs := []controller.Informer{} + for _, selector := range labelSelectors { + f := filtered.Get(ctx, selector) + inf := f.Rbac().V1().Roles() + ctx = context.WithValue(ctx, Key{Selector: selector}, inf) + infs = append(infs, inf.Informer()) + } + return ctx, infs +} + +// Get extracts the typed informer from the context. +func Get(ctx context.Context, selector string) v1.RoleInformer { + untyped := ctx.Value(Key{Selector: selector}) + if untyped == nil { + logging.FromContext(ctx).Panicf( + "Unable to fetch k8s.io/client-go/informers/rbac/v1.RoleInformer with selector %s from context.", selector) + } + return untyped.(v1.RoleInformer) +} diff --git a/vendor/knative.dev/pkg/client/injection/kube/informers/rbac/v1/rolebinding/filtered/rolebinding.go b/vendor/knative.dev/pkg/client/injection/kube/informers/rbac/v1/rolebinding/filtered/rolebinding.go new file mode 100644 index 00000000000..79a6b880f46 --- /dev/null +++ b/vendor/knative.dev/pkg/client/injection/kube/informers/rbac/v1/rolebinding/filtered/rolebinding.go @@ -0,0 +1,65 @@ +/* +Copyright 2022 The Knative Authors + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +// Code generated by injection-gen. DO NOT EDIT. + +package filtered + +import ( + context "context" + + v1 "k8s.io/client-go/informers/rbac/v1" + filtered "knative.dev/pkg/client/injection/kube/informers/factory/filtered" + controller "knative.dev/pkg/controller" + injection "knative.dev/pkg/injection" + logging "knative.dev/pkg/logging" +) + +func init() { + injection.Default.RegisterFilteredInformers(withInformer) +} + +// Key is used for associating the Informer inside the context.Context. +type Key struct { + Selector string +} + +func withInformer(ctx context.Context) (context.Context, []controller.Informer) { + untyped := ctx.Value(filtered.LabelKey{}) + if untyped == nil { + logging.FromContext(ctx).Panic( + "Unable to fetch labelkey from context.") + } + labelSelectors := untyped.([]string) + infs := []controller.Informer{} + for _, selector := range labelSelectors { + f := filtered.Get(ctx, selector) + inf := f.Rbac().V1().RoleBindings() + ctx = context.WithValue(ctx, Key{Selector: selector}, inf) + infs = append(infs, inf.Informer()) + } + return ctx, infs +} + +// Get extracts the typed informer from the context. +func Get(ctx context.Context, selector string) v1.RoleBindingInformer { + untyped := ctx.Value(Key{Selector: selector}) + if untyped == nil { + logging.FromContext(ctx).Panicf( + "Unable to fetch k8s.io/client-go/informers/rbac/v1.RoleBindingInformer with selector %s from context.", selector) + } + return untyped.(v1.RoleBindingInformer) +} diff --git a/vendor/modules.txt b/vendor/modules.txt index bd3c4dcd4b0..d2d99e7346b 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -1263,10 +1263,13 @@ knative.dev/pkg/client/injection/kube/informers/core/v1/serviceaccount knative.dev/pkg/client/injection/kube/informers/core/v1/serviceaccount/fake knative.dev/pkg/client/injection/kube/informers/factory knative.dev/pkg/client/injection/kube/informers/factory/fake +knative.dev/pkg/client/injection/kube/informers/factory/filtered knative.dev/pkg/client/injection/kube/informers/rbac/v1/role knative.dev/pkg/client/injection/kube/informers/rbac/v1/role/fake +knative.dev/pkg/client/injection/kube/informers/rbac/v1/role/filtered knative.dev/pkg/client/injection/kube/informers/rbac/v1/rolebinding knative.dev/pkg/client/injection/kube/informers/rbac/v1/rolebinding/fake +knative.dev/pkg/client/injection/kube/informers/rbac/v1/rolebinding/filtered knative.dev/pkg/client/injection/kube/reconciler/core/v1/namespace knative.dev/pkg/codegen/cmd/injection-gen knative.dev/pkg/codegen/cmd/injection-gen/args From 35c43b6a9156f261ca0bd8480efb01808d1b0676 Mon Sep 17 00:00:00 2001 From: Leo Li Date: Wed, 13 Dec 2023 16:43:19 -0500 Subject: [PATCH 52/62] Change to use the filtered informer, and add the informer eventhandler for the role and rolebinding informers Signed-off-by: Leo Li --- pkg/reconciler/apiserversource/controller.go | 3 +++ 1 file changed, 3 insertions(+) diff --git a/pkg/reconciler/apiserversource/controller.go b/pkg/reconciler/apiserversource/controller.go index 7de60dfe042..df1196e82b7 100644 --- a/pkg/reconciler/apiserversource/controller.go +++ b/pkg/reconciler/apiserversource/controller.go @@ -19,6 +19,8 @@ package apiserversource import ( "context" + filtered "knative.dev/eventing/pkg/client/injection/informers/factory/filtered" + "knative.dev/eventing/pkg/apis/feature" "github.com/kelseyhightower/envconfig" @@ -63,6 +65,7 @@ func NewController( // Create a selector string selectorString := "role=oidc-token-creator" + ctx = filtered.WithSelectors(ctx, selectorString) roleInformer := roleinformer.Get(ctx, selectorString) rolebindingInformer := rolebindinginformer.Get(ctx, selectorString) From c8254e58edbf8a32bda32958ec872774cfef1aa4 Mon Sep 17 00:00:00 2001 From: Leo Li Date: Thu, 14 Dec 2023 11:54:01 -0500 Subject: [PATCH 53/62] Inject the oidcSelector in the main.go Signed-off-by: Leo Li --- cmd/controller/main.go | 4 ++++ pkg/reconciler/apiserversource/controller.go | 10 ++++------ .../factory/filtered/filtered_factory.go | 19 +++++++++++++++++++ vendor/modules.txt | 1 + 4 files changed, 28 insertions(+), 6 deletions(-) create mode 100644 vendor/knative.dev/pkg/client/injection/informers/factory/filtered/filtered_factory.go diff --git a/cmd/controller/main.go b/cmd/controller/main.go index 9e81cc90f45..46e7c8d4f0c 100644 --- a/cmd/controller/main.go +++ b/cmd/controller/main.go @@ -26,6 +26,7 @@ import ( "os" "time" + filteredFactory "knative.dev/pkg/client/injection/kube/informers/factory/filtered" "knative.dev/pkg/injection/sharedmain" "knative.dev/pkg/signals" @@ -73,6 +74,9 @@ func main() { } }() + oidcSelector := "role=oidc-token-creator" + ctx = filteredFactory.WithSelectors(ctx, oidcSelector) + sharedmain.MainWithContext(ctx, "controller", // Messaging channel.NewController, diff --git a/pkg/reconciler/apiserversource/controller.go b/pkg/reconciler/apiserversource/controller.go index df1196e82b7..e3b571e107a 100644 --- a/pkg/reconciler/apiserversource/controller.go +++ b/pkg/reconciler/apiserversource/controller.go @@ -19,8 +19,6 @@ package apiserversource import ( "context" - filtered "knative.dev/eventing/pkg/client/injection/informers/factory/filtered" - "knative.dev/eventing/pkg/apis/feature" "github.com/kelseyhightower/envconfig" @@ -64,10 +62,10 @@ func NewController( serviceaccountInformer := serviceaccountinformer.Get(ctx) // Create a selector string - selectorString := "role=oidc-token-creator" - ctx = filtered.WithSelectors(ctx, selectorString) - roleInformer := roleinformer.Get(ctx, selectorString) - rolebindingInformer := rolebindinginformer.Get(ctx, selectorString) + + oidcSelectorString := "role=oidc-token-creator" + roleInformer := roleinformer.Get(ctx, oidcSelectorString) + rolebindingInformer := rolebindinginformer.Get(ctx, oidcSelectorString) var globalResync func(obj interface{}) diff --git a/vendor/knative.dev/pkg/client/injection/informers/factory/filtered/filtered_factory.go b/vendor/knative.dev/pkg/client/injection/informers/factory/filtered/filtered_factory.go new file mode 100644 index 00000000000..bd249facae7 --- /dev/null +++ b/vendor/knative.dev/pkg/client/injection/informers/factory/filtered/filtered_factory.go @@ -0,0 +1,19 @@ +/* +Copyright 2022 The Knative Authors + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +// Code generated by injection-gen. DO NOT EDIT. + +package filteredFactory diff --git a/vendor/modules.txt b/vendor/modules.txt index d2d99e7346b..958f3885d15 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -1241,6 +1241,7 @@ knative.dev/pkg/client/injection/ducks/duck/v1/source/fake knative.dev/pkg/client/injection/ducks/duck/v1alpha1/addressable knative.dev/pkg/client/injection/ducks/duck/v1beta1/addressable knative.dev/pkg/client/injection/ducks/duck/v1beta1/addressable/fake +knative.dev/pkg/client/injection/informers/factory/filtered knative.dev/pkg/client/injection/kube/client knative.dev/pkg/client/injection/kube/client/fake knative.dev/pkg/client/injection/kube/informers/admissionregistration/v1/mutatingwebhookconfiguration From 30b7d220424d37b32d074913fa46489ef8557f75 Mon Sep 17 00:00:00 2001 From: Leo Li Date: Thu, 14 Dec 2023 11:56:50 -0500 Subject: [PATCH 54/62] Add the owner reference to the role and rolebinding Signed-off-by: Leo Li --- pkg/reconciler/apiserversource/controller.go | 1 - .../apiserversource/resources/oidc_rolebinding.go | 6 ++++++ 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/pkg/reconciler/apiserversource/controller.go b/pkg/reconciler/apiserversource/controller.go index e3b571e107a..69f17df26e4 100644 --- a/pkg/reconciler/apiserversource/controller.go +++ b/pkg/reconciler/apiserversource/controller.go @@ -62,7 +62,6 @@ func NewController( serviceaccountInformer := serviceaccountinformer.Get(ctx) // Create a selector string - oidcSelectorString := "role=oidc-token-creator" roleInformer := roleinformer.Get(ctx, oidcSelectorString) rolebindingInformer := rolebindinginformer.Get(ctx, oidcSelectorString) diff --git a/pkg/reconciler/apiserversource/resources/oidc_rolebinding.go b/pkg/reconciler/apiserversource/resources/oidc_rolebinding.go index 64625c9d2c0..90731322adf 100644 --- a/pkg/reconciler/apiserversource/resources/oidc_rolebinding.go +++ b/pkg/reconciler/apiserversource/resources/oidc_rolebinding.go @@ -54,6 +54,9 @@ func MakeOIDCRole(source *v1.ApiServerSource) (*rbacv1.Role, error) { Labels: map[string]string{ "role": "oidc-token-creator", }, + OwnerReferences: []metav1.OwnerReference{ + *kmeta.NewControllerRef(source), + }, }, Rules: []rbacv1.PolicyRule{ rbacv1.PolicyRule{ @@ -89,6 +92,9 @@ func MakeOIDCRoleBinding(source *v1.ApiServerSource) (*rbacv1.RoleBinding, error Labels: map[string]string{ "role": "oidc-token-creator", }, + OwnerReferences: []metav1.OwnerReference{ + *kmeta.NewControllerRef(source), + }, }, RoleRef: rbacv1.RoleRef{ APIGroup: "rbac.authorization.k8s.io", From 72b37edaa2ef8d7739427efb61cc8665150f574a Mon Sep 17 00:00:00 2001 From: Leo Li Date: Thu, 14 Dec 2023 12:14:39 -0500 Subject: [PATCH 55/62] Update the tests Signed-off-by: Leo Li --- .../apiserversource/apiserversource_test.go | 44 +++++++++++++++++++ 1 file changed, 44 insertions(+) diff --git a/pkg/reconciler/apiserversource/apiserversource_test.go b/pkg/reconciler/apiserversource/apiserversource_test.go index f50da246dcc..df389c9d271 100644 --- a/pkg/reconciler/apiserversource/apiserversource_test.go +++ b/pkg/reconciler/apiserversource/apiserversource_test.go @@ -21,6 +21,8 @@ import ( "fmt" "testing" + "knative.dev/pkg/kmeta" + rbacv1 "k8s.io/api/rbac/v1" "github.com/stretchr/testify/require" @@ -1337,6 +1339,21 @@ func makeSubjectAccessReview(resource, verb, sa string) *authorizationv1.Subject } func makeOIDCRole() *rbacv1.Role { + src := rttestingv1.NewApiServerSource(sourceName, testNS, + rttestingv1.WithApiServerSourceSpec(sourcesv1.ApiServerSourceSpec{ + Resources: []sourcesv1.APIVersionKindSelector{{ + APIVersion: "v1", + Kind: "Namespace", + }}, + EventMode: sourcesv1.ResourceMode, + SourceSpec: duckv1.SourceSpec{Sink: sinkDest}, + }), + rttestingv1.WithApiServerSourceUID(sourceUID), + // Status Update: + rttestingv1.WithInitApiServerSourceConditions, + rttestingv1.WithApiServerSourceDeployed, + rttestingv1.WithApiServerSourceSink(sinkURI), + ) return &rbacv1.Role{ ObjectMeta: metav1.ObjectMeta{ Name: resources.GetOIDCTokenRoleName(sourceName), @@ -1344,6 +1361,12 @@ func makeOIDCRole() *rbacv1.Role { Annotations: map[string]string{ "description": fmt.Sprintf("Role for OIDC Authentication for ApiServerSource %q", sourceName), }, + Labels: map[string]string{ + "role": "oidc-token-creator", + }, + OwnerReferences: []metav1.OwnerReference{ + *kmeta.NewControllerRef(src), + }, }, Rules: []rbacv1.PolicyRule{ { @@ -1358,6 +1381,21 @@ func makeOIDCRole() *rbacv1.Role { } func makeOIDCRoleBinding() *rbacv1.RoleBinding { + src := rttestingv1.NewApiServerSource(sourceName, testNS, + rttestingv1.WithApiServerSourceSpec(sourcesv1.ApiServerSourceSpec{ + Resources: []sourcesv1.APIVersionKindSelector{{ + APIVersion: "v1", + Kind: "Namespace", + }}, + EventMode: sourcesv1.ResourceMode, + SourceSpec: duckv1.SourceSpec{Sink: sinkDest}, + }), + rttestingv1.WithApiServerSourceUID(sourceUID), + // Status Update: + rttestingv1.WithInitApiServerSourceConditions, + rttestingv1.WithApiServerSourceDeployed, + rttestingv1.WithApiServerSourceSink(sinkURI), + ) return &rbacv1.RoleBinding{ ObjectMeta: metav1.ObjectMeta{ Name: resources.GetOIDCTokenRoleBindingName(sourceName), @@ -1365,6 +1403,12 @@ func makeOIDCRoleBinding() *rbacv1.RoleBinding { Annotations: map[string]string{ "description": fmt.Sprintf("Role Binding for OIDC Authentication for ApiServerSource %q", sourceName), }, + Labels: map[string]string{ + "role": "oidc-token-creator", + }, + OwnerReferences: []metav1.OwnerReference{ + *kmeta.NewControllerRef(src), + }, }, RoleRef: rbacv1.RoleRef{ APIGroup: "rbac.authorization.k8s.io", From 55c172494806f7420a4bfc913677ef3b29957336 Mon Sep 17 00:00:00 2001 From: Leo Li Date: Fri, 15 Dec 2023 01:41:36 -0500 Subject: [PATCH 56/62] Update the tests Signed-off-by: Leo Li --- .../apiserversource/controller_test.go | 7 +++++++ .../factory/filtered/filtered_factory.go | 19 ------------------- vendor/modules.txt | 1 - 3 files changed, 7 insertions(+), 20 deletions(-) delete mode 100644 vendor/knative.dev/pkg/client/injection/informers/factory/filtered/filtered_factory.go diff --git a/pkg/reconciler/apiserversource/controller_test.go b/pkg/reconciler/apiserversource/controller_test.go index f0063203323..7e93fc6625b 100644 --- a/pkg/reconciler/apiserversource/controller_test.go +++ b/pkg/reconciler/apiserversource/controller_test.go @@ -20,6 +20,8 @@ import ( "os" "testing" + filteredFactory "knative.dev/pkg/client/injection/kube/informers/factory/filtered" + "knative.dev/eventing/pkg/apis/feature" corev1 "k8s.io/api/core/v1" @@ -42,8 +44,13 @@ import ( func TestNew(t *testing.T) { ctx, _ := SetupFakeContext(t) + + oidcSelector := "role=oidc-token-creator" + ctx = filteredFactory.WithSelectors(ctx, oidcSelector) + ctx = withCfgHost(ctx, &rest.Config{Host: "unit_test"}) ctx = addressable.WithDuck(ctx) + os.Setenv("METRICS_DOMAIN", "knative.dev/eventing") os.Setenv("APISERVER_RA_IMAGE", "knative.dev/example") c := NewController(ctx, configmap.NewStaticWatcher(&corev1.ConfigMap{ diff --git a/vendor/knative.dev/pkg/client/injection/informers/factory/filtered/filtered_factory.go b/vendor/knative.dev/pkg/client/injection/informers/factory/filtered/filtered_factory.go deleted file mode 100644 index bd249facae7..00000000000 --- a/vendor/knative.dev/pkg/client/injection/informers/factory/filtered/filtered_factory.go +++ /dev/null @@ -1,19 +0,0 @@ -/* -Copyright 2022 The Knative Authors - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -// Code generated by injection-gen. DO NOT EDIT. - -package filteredFactory diff --git a/vendor/modules.txt b/vendor/modules.txt index 958f3885d15..d2d99e7346b 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -1241,7 +1241,6 @@ knative.dev/pkg/client/injection/ducks/duck/v1/source/fake knative.dev/pkg/client/injection/ducks/duck/v1alpha1/addressable knative.dev/pkg/client/injection/ducks/duck/v1beta1/addressable knative.dev/pkg/client/injection/ducks/duck/v1beta1/addressable/fake -knative.dev/pkg/client/injection/informers/factory/filtered knative.dev/pkg/client/injection/kube/client knative.dev/pkg/client/injection/kube/client/fake knative.dev/pkg/client/injection/kube/informers/admissionregistration/v1/mutatingwebhookconfiguration From 0d053b30c6ec250cfa243cca943b2e5ebb3bf74a Mon Sep 17 00:00:00 2001 From: Leo Li Date: Fri, 15 Dec 2023 10:41:24 -0500 Subject: [PATCH 57/62] nit fix Signed-off-by: Leo Li --- cmd/controller/main.go | 4 ++-- pkg/apis/sources/register.go | 3 +++ .../apiserversource/apiserversource_test.go | 24 ------------------- 3 files changed, 5 insertions(+), 26 deletions(-) diff --git a/cmd/controller/main.go b/cmd/controller/main.go index 46e7c8d4f0c..e37a2193580 100644 --- a/cmd/controller/main.go +++ b/cmd/controller/main.go @@ -21,6 +21,7 @@ import ( // _ "k8s.io/client-go/plugin/pkg/client/auth/gcp" "errors" + "knative.dev/eventing/pkg/apis/sources" "log" "net/http" "os" @@ -74,8 +75,7 @@ func main() { } }() - oidcSelector := "role=oidc-token-creator" - ctx = filteredFactory.WithSelectors(ctx, oidcSelector) + ctx = filteredFactory.WithSelectors(ctx, sources.OIDCInformerSelector) sharedmain.MainWithContext(ctx, "controller", // Messaging diff --git a/pkg/apis/sources/register.go b/pkg/apis/sources/register.go index 55b4a748b17..44ca453a90f 100644 --- a/pkg/apis/sources/register.go +++ b/pkg/apis/sources/register.go @@ -32,6 +32,9 @@ const ( // SourceDuckLabelValue is the label value to indicate // the CRD is a Source duck type. SourceDuckLabelValue = "true" + + // OIDCInformerSelector is the label selector for the OIDC token creator role and rolebinding informers + OIDCInformerSelector = "role=oidc-token-creator" ) var ( diff --git a/pkg/reconciler/apiserversource/apiserversource_test.go b/pkg/reconciler/apiserversource/apiserversource_test.go index df389c9d271..997212b4f0f 100644 --- a/pkg/reconciler/apiserversource/apiserversource_test.go +++ b/pkg/reconciler/apiserversource/apiserversource_test.go @@ -1340,19 +1340,7 @@ func makeSubjectAccessReview(resource, verb, sa string) *authorizationv1.Subject func makeOIDCRole() *rbacv1.Role { src := rttestingv1.NewApiServerSource(sourceName, testNS, - rttestingv1.WithApiServerSourceSpec(sourcesv1.ApiServerSourceSpec{ - Resources: []sourcesv1.APIVersionKindSelector{{ - APIVersion: "v1", - Kind: "Namespace", - }}, - EventMode: sourcesv1.ResourceMode, - SourceSpec: duckv1.SourceSpec{Sink: sinkDest}, - }), rttestingv1.WithApiServerSourceUID(sourceUID), - // Status Update: - rttestingv1.WithInitApiServerSourceConditions, - rttestingv1.WithApiServerSourceDeployed, - rttestingv1.WithApiServerSourceSink(sinkURI), ) return &rbacv1.Role{ ObjectMeta: metav1.ObjectMeta{ @@ -1382,19 +1370,7 @@ func makeOIDCRole() *rbacv1.Role { func makeOIDCRoleBinding() *rbacv1.RoleBinding { src := rttestingv1.NewApiServerSource(sourceName, testNS, - rttestingv1.WithApiServerSourceSpec(sourcesv1.ApiServerSourceSpec{ - Resources: []sourcesv1.APIVersionKindSelector{{ - APIVersion: "v1", - Kind: "Namespace", - }}, - EventMode: sourcesv1.ResourceMode, - SourceSpec: duckv1.SourceSpec{Sink: sinkDest}, - }), rttestingv1.WithApiServerSourceUID(sourceUID), - // Status Update: - rttestingv1.WithInitApiServerSourceConditions, - rttestingv1.WithApiServerSourceDeployed, - rttestingv1.WithApiServerSourceSink(sinkURI), ) return &rbacv1.RoleBinding{ ObjectMeta: metav1.ObjectMeta{ From c082ede1d7e59f5091945f8a2af346851b59bbf7 Mon Sep 17 00:00:00 2001 From: Leo Li Date: Fri, 15 Dec 2023 11:39:19 -0500 Subject: [PATCH 58/62] register the selectors Signed-off-by: Leo Li --- pkg/reconciler/apiserversource/controller.go | 7 ++- .../apiserversource/controller_test.go | 15 +++-- .../filtered/fake/fake_filtered_factory.go | 60 +++++++++++++++++++ .../rbac/v1/role/filtered/fake/fake.go | 52 ++++++++++++++++ .../rbac/v1/rolebinding/filtered/fake/fake.go | 52 ++++++++++++++++ vendor/modules.txt | 3 + 6 files changed, 182 insertions(+), 7 deletions(-) create mode 100644 vendor/knative.dev/pkg/client/injection/kube/informers/factory/filtered/fake/fake_filtered_factory.go create mode 100644 vendor/knative.dev/pkg/client/injection/kube/informers/rbac/v1/role/filtered/fake/fake.go create mode 100644 vendor/knative.dev/pkg/client/injection/kube/informers/rbac/v1/rolebinding/filtered/fake/fake.go diff --git a/pkg/reconciler/apiserversource/controller.go b/pkg/reconciler/apiserversource/controller.go index 69f17df26e4..8859a78bcba 100644 --- a/pkg/reconciler/apiserversource/controller.go +++ b/pkg/reconciler/apiserversource/controller.go @@ -19,6 +19,8 @@ package apiserversource import ( "context" + "knative.dev/eventing/pkg/apis/sources" + "knative.dev/eventing/pkg/apis/feature" "github.com/kelseyhightower/envconfig" @@ -62,9 +64,8 @@ func NewController( serviceaccountInformer := serviceaccountinformer.Get(ctx) // Create a selector string - oidcSelectorString := "role=oidc-token-creator" - roleInformer := roleinformer.Get(ctx, oidcSelectorString) - rolebindingInformer := rolebindinginformer.Get(ctx, oidcSelectorString) + roleInformer := roleinformer.Get(ctx, sources.OIDCInformerSelector) + rolebindingInformer := rolebindinginformer.Get(ctx, sources.OIDCInformerSelector) var globalResync func(obj interface{}) diff --git a/pkg/reconciler/apiserversource/controller_test.go b/pkg/reconciler/apiserversource/controller_test.go index 7e93fc6625b..b0378597617 100644 --- a/pkg/reconciler/apiserversource/controller_test.go +++ b/pkg/reconciler/apiserversource/controller_test.go @@ -17,9 +17,11 @@ limitations under the License. package apiserversource import ( + "context" "os" "testing" + "knative.dev/eventing/pkg/apis/sources" filteredFactory "knative.dev/pkg/client/injection/kube/informers/factory/filtered" "knative.dev/eventing/pkg/apis/feature" @@ -39,14 +41,14 @@ import ( _ "knative.dev/pkg/client/injection/kube/informers/apps/v1/deployment/fake" _ "knative.dev/pkg/client/injection/kube/informers/core/v1/namespace/fake" _ "knative.dev/pkg/client/injection/kube/informers/core/v1/serviceaccount/fake" + _ "knative.dev/pkg/client/injection/kube/informers/factory/filtered/fake" + _ "knative.dev/pkg/client/injection/kube/informers/rbac/v1/role/filtered/fake" + _ "knative.dev/pkg/client/injection/kube/informers/rbac/v1/rolebinding/filtered/fake" . "knative.dev/pkg/reconciler/testing" ) func TestNew(t *testing.T) { - ctx, _ := SetupFakeContext(t) - - oidcSelector := "role=oidc-token-creator" - ctx = filteredFactory.WithSelectors(ctx, oidcSelector) + ctx, _ := SetupFakeContext(t, SetUpInformerSelector) ctx = withCfgHost(ctx, &rest.Config{Host: "unit_test"}) ctx = addressable.WithDuck(ctx) @@ -90,3 +92,8 @@ func TestNew(t *testing.T) { t.Fatal("Expected NewController to return a non-nil value") } } + +func SetUpInformerSelector(ctx context.Context) context.Context { + ctx = filteredFactory.WithSelectors(ctx, sources.OIDCInformerSelector) + return ctx +} diff --git a/vendor/knative.dev/pkg/client/injection/kube/informers/factory/filtered/fake/fake_filtered_factory.go b/vendor/knative.dev/pkg/client/injection/kube/informers/factory/filtered/fake/fake_filtered_factory.go new file mode 100644 index 00000000000..b5bb695d292 --- /dev/null +++ b/vendor/knative.dev/pkg/client/injection/kube/informers/factory/filtered/fake/fake_filtered_factory.go @@ -0,0 +1,60 @@ +/* +Copyright 2022 The Knative Authors + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +// Code generated by injection-gen. DO NOT EDIT. + +package fakeFilteredFactory + +import ( + context "context" + + v1 "k8s.io/apimachinery/pkg/apis/meta/v1" + informers "k8s.io/client-go/informers" + fake "knative.dev/pkg/client/injection/kube/client/fake" + filtered "knative.dev/pkg/client/injection/kube/informers/factory/filtered" + controller "knative.dev/pkg/controller" + injection "knative.dev/pkg/injection" + logging "knative.dev/pkg/logging" +) + +var Get = filtered.Get + +func init() { + injection.Fake.RegisterInformerFactory(withInformerFactory) +} + +func withInformerFactory(ctx context.Context) context.Context { + c := fake.Get(ctx) + untyped := ctx.Value(filtered.LabelKey{}) + if untyped == nil { + logging.FromContext(ctx).Panic( + "Unable to fetch labelkey from context.") + } + labelSelectors := untyped.([]string) + for _, selector := range labelSelectors { + selectorVal := selector + opts := []informers.SharedInformerOption{} + if injection.HasNamespaceScope(ctx) { + opts = append(opts, informers.WithNamespace(injection.GetNamespaceScope(ctx))) + } + opts = append(opts, informers.WithTweakListOptions(func(l *v1.ListOptions) { + l.LabelSelector = selectorVal + })) + ctx = context.WithValue(ctx, filtered.Key{Selector: selectorVal}, + informers.NewSharedInformerFactoryWithOptions(c, controller.GetResyncPeriod(ctx), opts...)) + } + return ctx +} diff --git a/vendor/knative.dev/pkg/client/injection/kube/informers/rbac/v1/role/filtered/fake/fake.go b/vendor/knative.dev/pkg/client/injection/kube/informers/rbac/v1/role/filtered/fake/fake.go new file mode 100644 index 00000000000..0223a6b3603 --- /dev/null +++ b/vendor/knative.dev/pkg/client/injection/kube/informers/rbac/v1/role/filtered/fake/fake.go @@ -0,0 +1,52 @@ +/* +Copyright 2022 The Knative Authors + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +// Code generated by injection-gen. DO NOT EDIT. + +package fake + +import ( + context "context" + + factoryfiltered "knative.dev/pkg/client/injection/kube/informers/factory/filtered" + filtered "knative.dev/pkg/client/injection/kube/informers/rbac/v1/role/filtered" + controller "knative.dev/pkg/controller" + injection "knative.dev/pkg/injection" + logging "knative.dev/pkg/logging" +) + +var Get = filtered.Get + +func init() { + injection.Fake.RegisterFilteredInformers(withInformer) +} + +func withInformer(ctx context.Context) (context.Context, []controller.Informer) { + untyped := ctx.Value(factoryfiltered.LabelKey{}) + if untyped == nil { + logging.FromContext(ctx).Panic( + "Unable to fetch labelkey from context.") + } + labelSelectors := untyped.([]string) + infs := []controller.Informer{} + for _, selector := range labelSelectors { + f := factoryfiltered.Get(ctx, selector) + inf := f.Rbac().V1().Roles() + ctx = context.WithValue(ctx, filtered.Key{Selector: selector}, inf) + infs = append(infs, inf.Informer()) + } + return ctx, infs +} diff --git a/vendor/knative.dev/pkg/client/injection/kube/informers/rbac/v1/rolebinding/filtered/fake/fake.go b/vendor/knative.dev/pkg/client/injection/kube/informers/rbac/v1/rolebinding/filtered/fake/fake.go new file mode 100644 index 00000000000..d736866dda9 --- /dev/null +++ b/vendor/knative.dev/pkg/client/injection/kube/informers/rbac/v1/rolebinding/filtered/fake/fake.go @@ -0,0 +1,52 @@ +/* +Copyright 2022 The Knative Authors + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +// Code generated by injection-gen. DO NOT EDIT. + +package fake + +import ( + context "context" + + factoryfiltered "knative.dev/pkg/client/injection/kube/informers/factory/filtered" + filtered "knative.dev/pkg/client/injection/kube/informers/rbac/v1/rolebinding/filtered" + controller "knative.dev/pkg/controller" + injection "knative.dev/pkg/injection" + logging "knative.dev/pkg/logging" +) + +var Get = filtered.Get + +func init() { + injection.Fake.RegisterFilteredInformers(withInformer) +} + +func withInformer(ctx context.Context) (context.Context, []controller.Informer) { + untyped := ctx.Value(factoryfiltered.LabelKey{}) + if untyped == nil { + logging.FromContext(ctx).Panic( + "Unable to fetch labelkey from context.") + } + labelSelectors := untyped.([]string) + infs := []controller.Informer{} + for _, selector := range labelSelectors { + f := factoryfiltered.Get(ctx, selector) + inf := f.Rbac().V1().RoleBindings() + ctx = context.WithValue(ctx, filtered.Key{Selector: selector}, inf) + infs = append(infs, inf.Informer()) + } + return ctx, infs +} diff --git a/vendor/modules.txt b/vendor/modules.txt index d2d99e7346b..c8b92c979cd 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -1264,12 +1264,15 @@ knative.dev/pkg/client/injection/kube/informers/core/v1/serviceaccount/fake knative.dev/pkg/client/injection/kube/informers/factory knative.dev/pkg/client/injection/kube/informers/factory/fake knative.dev/pkg/client/injection/kube/informers/factory/filtered +knative.dev/pkg/client/injection/kube/informers/factory/filtered/fake knative.dev/pkg/client/injection/kube/informers/rbac/v1/role knative.dev/pkg/client/injection/kube/informers/rbac/v1/role/fake knative.dev/pkg/client/injection/kube/informers/rbac/v1/role/filtered +knative.dev/pkg/client/injection/kube/informers/rbac/v1/role/filtered/fake knative.dev/pkg/client/injection/kube/informers/rbac/v1/rolebinding knative.dev/pkg/client/injection/kube/informers/rbac/v1/rolebinding/fake knative.dev/pkg/client/injection/kube/informers/rbac/v1/rolebinding/filtered +knative.dev/pkg/client/injection/kube/informers/rbac/v1/rolebinding/filtered/fake knative.dev/pkg/client/injection/kube/reconciler/core/v1/namespace knative.dev/pkg/codegen/cmd/injection-gen knative.dev/pkg/codegen/cmd/injection-gen/args From 62fe5705d15ee5a71cac10e6f6f4f978baf3a802 Mon Sep 17 00:00:00 2001 From: Leo Li Date: Fri, 15 Dec 2023 12:03:16 -0500 Subject: [PATCH 59/62] nit: fix the go imports Signed-off-by: Leo Li --- cmd/controller/main.go | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/cmd/controller/main.go b/cmd/controller/main.go index e37a2193580..dda6761aba9 100644 --- a/cmd/controller/main.go +++ b/cmd/controller/main.go @@ -21,12 +21,13 @@ import ( // _ "k8s.io/client-go/plugin/pkg/client/auth/gcp" "errors" - "knative.dev/eventing/pkg/apis/sources" "log" "net/http" "os" "time" + "knative.dev/eventing/pkg/apis/sources" + filteredFactory "knative.dev/pkg/client/injection/kube/informers/factory/filtered" "knative.dev/pkg/injection/sharedmain" "knative.dev/pkg/signals" From f8b479589f1e5cf1a70dda936dad82860353f2cd Mon Sep 17 00:00:00 2001 From: Leo Li Date: Mon, 18 Dec 2023 09:25:20 -0500 Subject: [PATCH 60/62] nit: renaming the variables and only filter on the labelKey (e.g. by using only the selector oidc) and not by value Signed-off-by: Leo Li --- cmd/controller/main.go | 2 +- pkg/apis/sources/register.go | 6 ++++-- pkg/reconciler/apiserversource/controller.go | 4 ++-- pkg/reconciler/apiserversource/controller_test.go | 2 +- .../apiserversource/resources/oidc_rolebinding.go | 6 ++++-- 5 files changed, 12 insertions(+), 8 deletions(-) diff --git a/cmd/controller/main.go b/cmd/controller/main.go index dda6761aba9..b28ca7852c8 100644 --- a/cmd/controller/main.go +++ b/cmd/controller/main.go @@ -76,7 +76,7 @@ func main() { } }() - ctx = filteredFactory.WithSelectors(ctx, sources.OIDCInformerSelector) + ctx = filteredFactory.WithSelectors(ctx, sources.OIDCTokenRoleLabelSelector) sharedmain.MainWithContext(ctx, "controller", // Messaging diff --git a/pkg/apis/sources/register.go b/pkg/apis/sources/register.go index 44ca453a90f..a549265036b 100644 --- a/pkg/apis/sources/register.go +++ b/pkg/apis/sources/register.go @@ -33,8 +33,10 @@ const ( // the CRD is a Source duck type. SourceDuckLabelValue = "true" - // OIDCInformerSelector is the label selector for the OIDC token creator role and rolebinding informers - OIDCInformerSelector = "role=oidc-token-creator" + OIDCLabelKey = "oidc" + + // OIDCTokenRoleLabelSelector is the label selector for the OIDC token creator role and rolebinding informers + OIDCTokenRoleLabelSelector = OIDCLabelKey ) var ( diff --git a/pkg/reconciler/apiserversource/controller.go b/pkg/reconciler/apiserversource/controller.go index 8859a78bcba..ae0e38bd191 100644 --- a/pkg/reconciler/apiserversource/controller.go +++ b/pkg/reconciler/apiserversource/controller.go @@ -64,8 +64,8 @@ func NewController( serviceaccountInformer := serviceaccountinformer.Get(ctx) // Create a selector string - roleInformer := roleinformer.Get(ctx, sources.OIDCInformerSelector) - rolebindingInformer := rolebindinginformer.Get(ctx, sources.OIDCInformerSelector) + roleInformer := roleinformer.Get(ctx, sources.OIDCTokenRoleLabelSelector) + rolebindingInformer := rolebindinginformer.Get(ctx, sources.OIDCTokenRoleLabelSelector) var globalResync func(obj interface{}) diff --git a/pkg/reconciler/apiserversource/controller_test.go b/pkg/reconciler/apiserversource/controller_test.go index b0378597617..16d9a5df23c 100644 --- a/pkg/reconciler/apiserversource/controller_test.go +++ b/pkg/reconciler/apiserversource/controller_test.go @@ -94,6 +94,6 @@ func TestNew(t *testing.T) { } func SetUpInformerSelector(ctx context.Context) context.Context { - ctx = filteredFactory.WithSelectors(ctx, sources.OIDCInformerSelector) + ctx = filteredFactory.WithSelectors(ctx, sources.OIDCTokenRoleLabelSelector) return ctx } diff --git a/pkg/reconciler/apiserversource/resources/oidc_rolebinding.go b/pkg/reconciler/apiserversource/resources/oidc_rolebinding.go index 90731322adf..92cd2464243 100644 --- a/pkg/reconciler/apiserversource/resources/oidc_rolebinding.go +++ b/pkg/reconciler/apiserversource/resources/oidc_rolebinding.go @@ -19,6 +19,8 @@ package resources import ( "fmt" + "knative.dev/eventing/pkg/apis/sources" + "knative.dev/pkg/kmeta" rbacv1 "k8s.io/api/rbac/v1" @@ -52,7 +54,7 @@ func MakeOIDCRole(source *v1.ApiServerSource) (*rbacv1.Role, error) { "description": fmt.Sprintf("Role for OIDC Authentication for ApiServerSource %q", source.GetName()), }, Labels: map[string]string{ - "role": "oidc-token-creator", + sources.OIDCLabelKey: "", }, OwnerReferences: []metav1.OwnerReference{ *kmeta.NewControllerRef(source), @@ -90,7 +92,7 @@ func MakeOIDCRoleBinding(source *v1.ApiServerSource) (*rbacv1.RoleBinding, error "description": fmt.Sprintf("Role Binding for OIDC Authentication for ApiServerSource %q", source.GetName()), }, Labels: map[string]string{ - "role": "oidc-token-creator", + sources.OIDCLabelKey: "", }, OwnerReferences: []metav1.OwnerReference{ *kmeta.NewControllerRef(source), From a73a26bb64ccb9de8beaa443001e7753d1732e1e Mon Sep 17 00:00:00 2001 From: Leo Li Date: Mon, 18 Dec 2023 09:41:23 -0500 Subject: [PATCH 61/62] nit: renaming the variables and only filter on the labelKey (e.g. by using only the selector oidc) and not by value Signed-off-by: Leo Li --- pkg/reconciler/apiserversource/apiserversource_test.go | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/pkg/reconciler/apiserversource/apiserversource_test.go b/pkg/reconciler/apiserversource/apiserversource_test.go index 997212b4f0f..b6a15fdc0cd 100644 --- a/pkg/reconciler/apiserversource/apiserversource_test.go +++ b/pkg/reconciler/apiserversource/apiserversource_test.go @@ -21,6 +21,8 @@ import ( "fmt" "testing" + "knative.dev/eventing/pkg/apis/sources" + "knative.dev/pkg/kmeta" rbacv1 "k8s.io/api/rbac/v1" @@ -1350,7 +1352,7 @@ func makeOIDCRole() *rbacv1.Role { "description": fmt.Sprintf("Role for OIDC Authentication for ApiServerSource %q", sourceName), }, Labels: map[string]string{ - "role": "oidc-token-creator", + sources.OIDCLabelKey: "", }, OwnerReferences: []metav1.OwnerReference{ *kmeta.NewControllerRef(src), @@ -1380,7 +1382,7 @@ func makeOIDCRoleBinding() *rbacv1.RoleBinding { "description": fmt.Sprintf("Role Binding for OIDC Authentication for ApiServerSource %q", sourceName), }, Labels: map[string]string{ - "role": "oidc-token-creator", + sources.OIDCLabelKey: "", }, OwnerReferences: []metav1.OwnerReference{ *kmeta.NewControllerRef(src), From 8890c5db9533d655a74c9f563b620091f35459e8 Mon Sep 17 00:00:00 2001 From: Leo Li Date: Mon, 18 Dec 2023 10:11:44 -0500 Subject: [PATCH 62/62] nit: fix the naming and add - to the create-oidc-token Signed-off-by: Leo Li --- pkg/apis/sources/register.go | 1 + pkg/reconciler/apiserversource/resources/oidc_rolebinding.go | 4 ++-- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/pkg/apis/sources/register.go b/pkg/apis/sources/register.go index a549265036b..3cd87d78e75 100644 --- a/pkg/apis/sources/register.go +++ b/pkg/apis/sources/register.go @@ -33,6 +33,7 @@ const ( // the CRD is a Source duck type. SourceDuckLabelValue = "true" + //OIDCLabelKey is used to filter out all the informers that related to OIDC work OIDCLabelKey = "oidc" // OIDCTokenRoleLabelSelector is the label selector for the OIDC token creator role and rolebinding informers diff --git a/pkg/reconciler/apiserversource/resources/oidc_rolebinding.go b/pkg/reconciler/apiserversource/resources/oidc_rolebinding.go index 92cd2464243..0d0ca65dc72 100644 --- a/pkg/reconciler/apiserversource/resources/oidc_rolebinding.go +++ b/pkg/reconciler/apiserversource/resources/oidc_rolebinding.go @@ -30,12 +30,12 @@ import ( // GetOIDCTokenRoleName will return the name of the role for creating the JWT token func GetOIDCTokenRoleName(sourceName string) string { - return kmeta.ChildName(sourceName, "create-oidc-token") + return kmeta.ChildName(sourceName, "-create-oidc-token") } // GetOIDCTokenRoleBindingName will return the name of the rolebinding for creating the JWT token func GetOIDCTokenRoleBindingName(sourceName string) string { - return kmeta.ChildName(sourceName, "create-oidc-token") + return kmeta.ChildName(sourceName, "-create-oidc-token") } // MakeOIDCRole will return the role object config for generating the JWT token