From 0ef864a595c83a05a05d065bd2dd86bbcf3678d7 Mon Sep 17 00:00:00 2001 From: Aaron Weisberg Date: Tue, 15 Feb 2022 13:34:37 -0700 Subject: [PATCH] adds SigningCertURL validation Signed-off-by: Aaron Weisberg --- eventsources/sources/awssns/start.go | 17 +++++--- eventsources/sources/awssns/start_test.go | 47 +++++++++++++++++++++++ 2 files changed, 59 insertions(+), 5 deletions(-) create mode 100644 eventsources/sources/awssns/start_test.go diff --git a/eventsources/sources/awssns/start.go b/eventsources/sources/awssns/start.go index dd4f641b50..d6abb3a72a 100644 --- a/eventsources/sources/awssns/start.go +++ b/eventsources/sources/awssns/start.go @@ -25,6 +25,7 @@ import ( "encoding/pem" "io/ioutil" "net/http" + "net/url" "reflect" "regexp" "time" @@ -285,12 +286,18 @@ func (el *EventListener) StartListening(ctx context.Context, dispatch func([]byt }, controller, dispatch) } -const regexSigningCertURL = `/^https:\/\/sns\.[a-zA-Z0-9-]{3,}\.amazonaws\.com(\.cn)?\/SimpleNotificationService-[a-zA-Z0-9]{32}\.pem$/` - func (m *httpNotification) verifySigningCertUrl() error { - regex := regexp.MustCompile(regexSigningCertURL) - if !regex.MatchString(m.SigningCertURL) { - return errors.Errorf("SigningCertURL `%s` does not match `%s`", m.SigningCertURL, regexSigningCertURL) + regexSigningCertHost := `^sns\.[a-zA-Z0-9\-]{3,}\.amazonaws\.com(\.cn)?$` + regex := regexp.MustCompile(regexSigningCertHost) + url, err := url.Parse(m.SigningCertURL) + if err != nil { + return errors.Wrap(err, "SigningCertURL is not a valid URL") + } + if !regex.MatchString(url.Hostname()) { + return errors.Errorf("SigningCertURL hostname `%s` does not match `%s`", url.Hostname(), regexSigningCertHost) + } + if url.Scheme != "https" { + return errors.New("SigningCertURL is not using https") } return nil } diff --git a/eventsources/sources/awssns/start_test.go b/eventsources/sources/awssns/start_test.go new file mode 100644 index 0000000000..d8f8b8b7ba --- /dev/null +++ b/eventsources/sources/awssns/start_test.go @@ -0,0 +1,47 @@ +/* +Copyright 2018 BlackRock, Inc. + +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 awssns + +import ( + "testing" +) + +func Test_httpNotification_verifySigningCertUrl(t *testing.T) { + type fields struct { + SigningCertURL string + } + tests := map[string]struct { + fields fields + wantErr bool + }{ + "valid": {fields{"https://sns.us-west-2.amazonaws.com/SimpleNotificationService-123.pem"}, false}, + "without https": {fields{"http://sns.us-west-2.amazonaws.com/SimpleNotificationService-123.pem"}, true}, + "invalid hostname": {fields{"https://sns.us-west-2.amazonaws-malicious.com/SimpleNotificationService-123.pem"}, true}, + "invalid subdomain": {fields{"https://other.us-west-2.amazonaws.com/SimpleNotificationService-123.pem"}, true}, + } + for name, tt := range tests { + name, tt := name, tt + t.Run(name, func(t *testing.T) { + m := &httpNotification{ + SigningCertURL: tt.fields.SigningCertURL, + } + if err := m.verifySigningCertUrl(); (err != nil) != tt.wantErr { + t.Errorf("httpNotification.verifySigningCertUrl() error = %v, wantErr %v", err, tt.wantErr) + } + }) + } +}