Skip to content

Commit f81a866

Browse files
committed
Add support for blocking HTTP connections
Signed-off-by: Gunish Matta <[email protected]>
1 parent 921ebc0 commit f81a866

File tree

4 files changed

+92
-3
lines changed

4 files changed

+92
-3
lines changed

controllers/event_handling_test.go

Lines changed: 69 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import (
77
"fmt"
88
"net/http"
99
"net/http/httptest"
10+
"net/url"
1011
"testing"
1112
"time"
1213

@@ -52,7 +53,69 @@ func TestEventHandler(t *testing.T) {
5253
t.Fatalf("failed to create memory storage")
5354
}
5455

55-
eventServer := server.NewEventServer("127.0.0.1:56789", logf.Log, k8sClient, true)
56+
httpScheme := "http"
57+
58+
eventServerTests := []struct {
59+
name string
60+
isHttpEnabled bool
61+
url string
62+
}{
63+
{
64+
name: "http scheme is enabled",
65+
isHttpEnabled: true,
66+
}, {
67+
name: "http scheme is disabled",
68+
isHttpEnabled: false,
69+
},
70+
}
71+
for _, eventServerTest := range eventServerTests {
72+
t.Run(eventServerTest.name, func(t *testing.T) {
73+
74+
eventServer := server.NewEventServer("127.0.0.1:56789", logf.Log, k8sClient, true, eventServerTest.isHttpEnabled)
75+
76+
stopCh := make(chan struct{})
77+
go eventServer.ListenAndServe(stopCh, eventMdlw, store)
78+
requestsReceived := 0
79+
rcvServer := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
80+
requestsReceived = requestsReceived + 1
81+
req = r
82+
w.WriteHeader(200)
83+
}))
84+
defer rcvServer.Close()
85+
defer close(stopCh)
86+
87+
providerKey := types.NamespacedName{
88+
Name: fmt.Sprintf("provider-%s", randStringRunes(5)),
89+
Namespace: namespace,
90+
}
91+
provider = &notifyv1.Provider{
92+
ObjectMeta: metav1.ObjectMeta{
93+
Name: providerKey.Name,
94+
Namespace: providerKey.Namespace,
95+
},
96+
Spec: notifyv1.ProviderSpec{
97+
Type: "generic",
98+
Address: rcvServer.URL,
99+
},
100+
}
101+
102+
webhook_url, err := url.Parse(provider.Spec.Address)
103+
104+
g.Expect(err).ToNot(HaveOccurred())
105+
106+
if eventServerTest.isHttpEnabled {
107+
g.Expect(webhook_url.Scheme).To(Equal(httpScheme))
108+
g.Expect(requestsReceived).To(Equal(1))
109+
} else {
110+
g.Expect(webhook_url.Scheme).ToNot(Equal(httpScheme))
111+
g.Expect(requestsReceived).To(Equal(0))
112+
}
113+
114+
})
115+
}
116+
117+
eventServer := server.NewEventServer("127.0.0.1:56789", logf.Log, k8sClient, true, true)
118+
56119
stopCh := make(chan struct{})
57120
go eventServer.ListenAndServe(stopCh, eventMdlw, store)
58121

@@ -77,6 +140,9 @@ func TestEventHandler(t *testing.T) {
77140
Address: rcvServer.URL,
78141
},
79142
}
143+
144+
g.Expect(err).ToNot(HaveOccurred())
145+
80146
g.Expect(k8sClient.Create(context.Background(), provider)).To(Succeed())
81147
g.Eventually(func() bool {
82148
var obj notifyv1.Provider
@@ -173,6 +239,7 @@ func TestEventHandler(t *testing.T) {
173239
res, err := http.Post("http://localhost:56789/", "application/json", buf)
174240
g.Expect(err).ToNot(HaveOccurred())
175241
g.Expect(res.StatusCode).To(Equal(202)) // event_server responds with 202 Accepted
242+
176243
}
177244

178245
testForwarded := func() {
@@ -294,4 +361,5 @@ func TestEventHandler(t *testing.T) {
294361
req = nil
295362
})
296363
}
364+
297365
}

internal/server/event_handlers.go

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ import (
2424
"fmt"
2525
"io"
2626
"net/http"
27+
"net/url"
2728
"regexp"
2829
"strings"
2930
"time"
@@ -243,6 +244,22 @@ func (s *EventServer) handleEvent() func(w http.ResponseWriter, r *http.Request)
243244
continue
244245
}
245246

247+
webhookUrl, err := url.Parse(webhook)
248+
if err != nil {
249+
s.logger.Error(nil, "Error parsing webhook url",
250+
"reconciler kind", v1beta1.ProviderKind,
251+
"name", providerName.Name,
252+
"namespace", providerName.Namespace)
253+
continue
254+
}
255+
256+
if !s.supportHttpScheme && webhookUrl.Scheme == "http" {
257+
s.logger.Error(nil, "http scheme is blocked",
258+
"reconciler kind", v1beta1.ProviderKind,
259+
"name", providerName.Name,
260+
"namespace", providerName.Namespace)
261+
continue
262+
}
246263
factory := notifier.NewFactory(webhook, proxy, username, provider.Spec.Channel, token, headers, certPool, password)
247264
sender, err := factory.Notifier(provider.Spec.Type)
248265
if err != nil {

internal/server/event_server.go

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,15 +44,17 @@ type EventServer struct {
4444
logger logr.Logger
4545
kubeClient client.Client
4646
noCrossNamespaceRefs bool
47+
supportHttpScheme bool
4748
}
4849

4950
// NewEventServer returns an HTTP server that handles events
50-
func NewEventServer(port string, logger logr.Logger, kubeClient client.Client, noCrossNamespaceRefs bool) *EventServer {
51+
func NewEventServer(port string, logger logr.Logger, kubeClient client.Client, noCrossNamespaceRefs bool, supportHttpScheme bool) *EventServer {
5152
return &EventServer{
5253
port: port,
5354
logger: logger.WithName("event-server"),
5455
kubeClient: kubeClient,
5556
noCrossNamespaceRefs: noCrossNamespaceRefs,
57+
supportHttpScheme: supportHttpScheme,
5658
}
5759
}
5860

main.go

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,7 @@ func main() {
7272
leaderElectionOptions leaderelection.Options
7373
aclOptions acl.Options
7474
rateLimiterOptions helper.RateLimiterOptions
75+
insecureAllowHTTP bool
7576
)
7677

7778
flag.StringVar(&metricsAddr, "metrics-addr", ":8080", "The address the metric endpoint binds to.")
@@ -82,6 +83,7 @@ func main() {
8283
flag.BoolVar(&watchAllNamespaces, "watch-all-namespaces", true,
8384
"Watch for custom resources in all namespaces, if set to false it will only watch the runtime namespace.")
8485
flag.DurationVar(&rateLimitInterval, "rate-limit-interval", 5*time.Minute, "Interval in which rate limit has effect.")
86+
flag.BoolVar(&insecureAllowHTTP, "insecure-allow-http", true, "Enable the use of HTTP Scheme (no HTTPS) across all controller level objects. This is not recommended for production environments")
8587
clientOptions.BindFlags(flag.CommandLine)
8688
logOptions.BindFlags(flag.CommandLine)
8789
leaderElectionOptions.BindFlags(flag.CommandLine)
@@ -169,7 +171,7 @@ func main() {
169171
Registry: crtlmetrics.Registry,
170172
}),
171173
})
172-
eventServer := server.NewEventServer(eventsAddr, log, mgr.GetClient(), aclOptions.NoCrossNamespaceRefs)
174+
eventServer := server.NewEventServer(eventsAddr, log, mgr.GetClient(), aclOptions.NoCrossNamespaceRefs, insecureAllowHTTP)
173175
go eventServer.ListenAndServe(ctx.Done(), eventMdlw, store)
174176

175177
setupLog.Info("starting webhook receiver server", "addr", receiverAddr)

0 commit comments

Comments
 (0)