@@ -22,7 +22,6 @@ package main
2222
2323import (
2424 "context"
25- "encoding/json"
2625 "net"
2726 "os"
2827
@@ -36,11 +35,16 @@ import (
3635
3736 "github.com/kelseyhightower/envconfig"
3837 "go.uber.org/zap"
38+ metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
39+ "k8s.io/apimachinery/pkg/runtime/schema"
3940 "k8s.io/client-go/kubernetes"
4041 "k8s.io/utils/ptr"
4142 cmdbroker "knative.dev/eventing/cmd/broker"
4243 "knative.dev/eventing/pkg/apis/feature"
4344 "knative.dev/eventing/pkg/auth"
45+ eventingclient "knative.dev/eventing/pkg/client/clientset/versioned"
46+ eventinginformers "knative.dev/eventing/pkg/client/informers/externalversions"
47+ eventingv1alpha1listers "knative.dev/eventing/pkg/client/listers/eventing/v1alpha1"
4448 "knative.dev/eventing/pkg/eventingtls"
4549 "knative.dev/eventing/pkg/kncloudevents"
4650 "knative.dev/pkg/apis"
@@ -69,7 +73,11 @@ type envConfig struct {
6973 SinkNamespace string `envconfig:"SINK_NAMESPACE" required:"true"`
7074 SinkAudience * string `envconfig:"SINK_AUDIENCE"`
7175
72- AuthPolicies string `envconfig:"AUTH_POLICIES"`
76+ // Parent resource information for dynamic EventPolicy lookup
77+ ParentAPIVersion string `envconfig:"PARENT_API_VERSION" required:"true"`
78+ ParentKind string `envconfig:"PARENT_KIND" required:"true"`
79+ ParentName string `envconfig:"PARENT_NAME" required:"true"`
80+ ParentNamespace string `envconfig:"PARENT_NAMESPACE" required:"true"`
7381
7482 SinkTLSCertPath * string `envconfig:"SINK_TLS_CERT_FILE"`
7583 SinkTLSKeyPath * string `envconfig:"SINK_TLS_KEY_FILE"`
@@ -79,13 +87,14 @@ type envConfig struct {
7987// ProxyHandler handles HTTP requests and performs authentication/authorization
8088// before forwarding to the target service
8189type ProxyHandler struct {
82- kubeClient kubernetes.Interface
83- withContext func (ctx context.Context ) context.Context
84- authVerifier * auth.Verifier
85- httpProxy * httputil.ReverseProxy
86- httpsProxy * httputil.ReverseProxy
87- config envConfig
88- authSubjects []auth.SubjectsWithFilters
90+ kubeClient kubernetes.Interface
91+ withContext func (ctx context.Context ) context.Context
92+ authVerifier * auth.Verifier
93+ httpProxy * httputil.ReverseProxy
94+ httpsProxy * httputil.ReverseProxy
95+ config envConfig
96+ eventPolicyLister eventingv1alpha1listers.EventPolicyLister
97+ parentResourceGVK schema.GroupVersionKind
8998}
9099
91100func main () {
@@ -104,7 +113,14 @@ func main() {
104113
105114 featureStore := setupFeatureStore (ctx , logger , configMapWatcher )
106115
107- handler , err := createProxyHandler (ctx , config , logger , featureStore , configMapWatcher )
116+ // Create namespace-scoped EventPolicy informer
117+ eventPolicyLister , eventPolicyInformer , err := setupEventPolicyInformer (ctx , config , logger )
118+ if err != nil {
119+ logger .Fatalw ("Failed to setup EventPolicy informer" , zap .Error (err ))
120+ }
121+ informers = append (informers , eventPolicyInformer )
122+
123+ handler , err := createProxyHandler (ctx , config , logger , featureStore , configMapWatcher , eventPolicyLister )
108124 if err != nil {
109125 logger .Fatalw ("Failed to create proxy handler" , zap .Error (err ))
110126 }
@@ -166,21 +182,45 @@ func setupFeatureStore(_ context.Context, logger *zap.SugaredLogger, configMapWa
166182 return featureStore
167183}
168184
169- // createProxyHandler creates and configures the proxy handler
170- func createProxyHandler (ctx context.Context , config envConfig , logger * zap.SugaredLogger , featureStore * feature. Store , configMapWatcher * configmap. InformedWatcher ) ( * ProxyHandler , error ) {
171- var authSubjects []auth. SubjectsWithFilters
185+ // setupEventPolicyInformer creates a namespace-scoped EventPolicy informer
186+ func setupEventPolicyInformer (ctx context.Context , config envConfig , logger * zap.SugaredLogger ) (eventingv1alpha1listers. EventPolicyLister , controller. Informer , error ) {
187+ cfg := injection . GetConfig ( ctx )
172188
173- if len ( config . AuthPolicies ) > 0 {
174- if err := json . Unmarshal ([] byte ( config . AuthPolicies ), & authSubjects ); err != nil {
175- return nil , fmt . Errorf ( "failed to parse policies: %w" , err )
176- }
189+ // Create eventing client
190+ eventingClient , err := eventingclient . NewForConfig ( cfg )
191+ if err != nil {
192+ return nil , nil , fmt . Errorf ( "failed to create eventing client: %w" , err )
177193 }
178194
195+ // Create namespace-scoped informer factory
196+ eventingInformerFactory := eventinginformers .NewSharedInformerFactoryWithOptions (
197+ eventingClient ,
198+ 0 , // resyncPeriod - 0 means no resync
199+ eventinginformers .WithNamespace (config .ParentNamespace ),
200+ )
201+
202+ eventPolicyInformer := eventingInformerFactory .Eventing ().V1alpha1 ().EventPolicies ()
203+
204+ logger .Infof ("Created namespace-scoped EventPolicy informer for namespace %s" , config .ParentNamespace )
205+
206+ return eventPolicyInformer .Lister (), eventPolicyInformer .Informer (), nil
207+ }
208+
209+ // createProxyHandler creates and configures the proxy handler
210+ func createProxyHandler (ctx context.Context , config envConfig , logger * zap.SugaredLogger , featureStore * feature.Store , configMapWatcher * configmap.InformedWatcher , eventPolicyLister eventingv1alpha1listers.EventPolicyLister ) (* ProxyHandler , error ) {
211+ // Parse parent resource GVK
212+ gv , err := schema .ParseGroupVersion (config .ParentAPIVersion )
213+ if err != nil {
214+ return nil , fmt .Errorf ("failed to parse parent API version %q: %w" , config .ParentAPIVersion , err )
215+ }
216+ parentGVK := gv .WithKind (config .ParentKind )
217+
179218 handler := & ProxyHandler {
180- kubeClient : kubeclient .Get (ctx ),
181- authVerifier : auth .NewVerifier (ctx , nil , nil , configMapWatcher ),
182- config : config ,
183- authSubjects : authSubjects ,
219+ kubeClient : kubeclient .Get (ctx ),
220+ authVerifier : auth .NewVerifier (ctx , nil , nil , configMapWatcher ),
221+ config : config ,
222+ eventPolicyLister : eventPolicyLister ,
223+ parentResourceGVK : parentGVK ,
184224 }
185225
186226 handler .withContext = func (ctx context.Context ) context.Context {
@@ -251,7 +291,15 @@ func (h *ProxyHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
251291
252292 logger .Debugf ("Handling request to %s" , r .RequestURI )
253293
254- err := h .authVerifier .VerifyRequestFromSubjectsWithFilters (ctx , features , h .config .SinkAudience , h .authSubjects , h .config .SinkNamespace , r , w )
294+ // Get EventPolicies dynamically for the parent resource
295+ authSubjects , err := h .getAuthSubjects (logger )
296+ if err != nil {
297+ logger .Errorw ("Failed to get EventPolicies" , zap .Error (err ))
298+ http .Error (w , "Internal server error" , http .StatusInternalServerError )
299+ return
300+ }
301+
302+ err = h .authVerifier .VerifyRequestFromSubjectsWithFilters (ctx , features , h .config .SinkAudience , authSubjects , h .config .SinkNamespace , r , w )
255303 if err != nil {
256304 logger .Debugw ("Failed to verify AuthN and AuthZ" , zap .Error (err ))
257305 return
@@ -266,6 +314,35 @@ func (h *ProxyHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
266314 }
267315}
268316
317+ // getAuthSubjects retrieves EventPolicies for the parent resource and converts them to SubjectsWithFilters
318+ func (h * ProxyHandler ) getAuthSubjects (logger * zap.SugaredLogger ) ([]auth.SubjectsWithFilters , error ) {
319+ // Get EventPolicies applying to this resource
320+ policies , err := auth .GetEventPoliciesForResource (
321+ h .eventPolicyLister ,
322+ h .parentResourceGVK ,
323+ metav1.ObjectMeta {
324+ Name : h .config .ParentName ,
325+ Namespace : h .config .ParentNamespace ,
326+ },
327+ )
328+ if err != nil {
329+ return nil , fmt .Errorf ("failed to get EventPolicies: %w" , err )
330+ }
331+
332+ logger .Debugf ("Found %d EventPolicies for %s/%s" , len (policies ), h .config .ParentNamespace , h .config .ParentName )
333+
334+ // Convert EventPolicies to SubjectsWithFilters
335+ subjectsWithFilters := make ([]auth.SubjectsWithFilters , 0 , len (policies ))
336+ for _ , policy := range policies {
337+ subjectsWithFilters = append (subjectsWithFilters , auth.SubjectsWithFilters {
338+ Subjects : policy .Status .From ,
339+ Filters : policy .Spec .Filters ,
340+ })
341+ }
342+
343+ return subjectsWithFilters , nil
344+ }
345+
269346// httpReverseProxy creates a reverse proxy for HTTP traffic to the target service
270347func httpReverseProxy (config envConfig ) (* httputil.ReverseProxy , error ) {
271348 httpTarget := fmt .Sprintf ("http://%s:%d" , config .TargetHost , config .TargetHTTPPort )
0 commit comments