From 7b17f5657e1cf6666693f46ea0846d823b083d9f Mon Sep 17 00:00:00 2001 From: Nathaniel Caza Date: Wed, 24 Aug 2022 09:11:27 -0500 Subject: [PATCH 1/4] add alternate auth token for use during key rotation --- config/config.go | 6 ++++-- graphql2/mapconfig.go | 5 ++++- notification/twilio/validation.go | 9 ++++++++- web/src/schema.d.ts | 1 + 4 files changed, 17 insertions(+), 4 deletions(-) diff --git a/config/config.go b/config/config.go index fdec57f601..7024c8fc12 100644 --- a/config/config.go +++ b/config/config.go @@ -97,8 +97,10 @@ type Config struct { Twilio struct { Enable bool `public:"true" info:"Enables sending and processing of Voice and SMS messages through the Twilio notification provider."` - AccountSID string - AuthToken string `password:"true" info:"The primary Auth Token for Twilio. Must be primary (not secondary) for request valiation."` + AccountSID string + AuthToken string `password:"true" info:"The primary Auth Token for Twilio. Must be primary Unless Alternate Auth Token is set."` + AlternateAuthToken string `password:"true" info:"An alternate Auth Token for validating requests. During a key change, set this to the current Primary, and Auth Token to Secondary, then promote and then clear this field."` + FromNumber string `public:"true" info:"The Twilio number to use for outgoing notifications."` MessagingServiceSID string `public:"true" info:"If set, replaces the use of From Number for SMS notifications."` diff --git a/graphql2/mapconfig.go b/graphql2/mapconfig.go index b22b18b021..67de5aa876 100644 --- a/graphql2/mapconfig.go +++ b/graphql2/mapconfig.go @@ -67,7 +67,8 @@ func MapConfigValues(cfg config.Config) []ConfigValue { {ID: "Slack.InteractiveMessages", Type: ConfigTypeBoolean, Description: "Enable interactive messages (e.g. buttons).", Value: fmt.Sprintf("%t", cfg.Slack.InteractiveMessages)}, {ID: "Twilio.Enable", Type: ConfigTypeBoolean, Description: "Enables sending and processing of Voice and SMS messages through the Twilio notification provider.", Value: fmt.Sprintf("%t", cfg.Twilio.Enable)}, {ID: "Twilio.AccountSID", Type: ConfigTypeString, Description: "", Value: cfg.Twilio.AccountSID}, - {ID: "Twilio.AuthToken", Type: ConfigTypeString, Description: "The primary Auth Token for Twilio. Must be primary (not secondary) for request valiation.", Value: cfg.Twilio.AuthToken, Password: true}, + {ID: "Twilio.AuthToken", Type: ConfigTypeString, Description: "The primary Auth Token for Twilio. Must be primary Unless Alternate Auth Token is set.", Value: cfg.Twilio.AuthToken, Password: true}, + {ID: "Twilio.AlternateAuthToken", Type: ConfigTypeString, Description: "An alternate Auth Token for validating requests. During a key change, set this to the current Primary, and Auth Token to Secondary, then promote and then clear this field.", Value: cfg.Twilio.AlternateAuthToken, Password: true}, {ID: "Twilio.FromNumber", Type: ConfigTypeString, Description: "The Twilio number to use for outgoing notifications.", Value: cfg.Twilio.FromNumber}, {ID: "Twilio.MessagingServiceSID", Type: ConfigTypeString, Description: "If set, replaces the use of From Number for SMS notifications.", Value: cfg.Twilio.MessagingServiceSID}, {ID: "Twilio.DisableTwoWaySMS", Type: ConfigTypeBoolean, Description: "Disables SMS reply codes for alert messages.", Value: fmt.Sprintf("%t", cfg.Twilio.DisableTwoWaySMS)}, @@ -299,6 +300,8 @@ func ApplyConfigValues(cfg config.Config, vals []ConfigValueInput) (config.Confi cfg.Twilio.AccountSID = v.Value case "Twilio.AuthToken": cfg.Twilio.AuthToken = v.Value + case "Twilio.AlternateAuthToken": + cfg.Twilio.AlternateAuthToken = v.Value case "Twilio.FromNumber": cfg.Twilio.FromNumber = v.Value case "Twilio.MessagingServiceSID": diff --git a/notification/twilio/validation.go b/notification/twilio/validation.go index 854c8fa545..950b62399d 100644 --- a/notification/twilio/validation.go +++ b/notification/twilio/validation.go @@ -25,7 +25,14 @@ func validateRequest(req *http.Request) error { calcSig := Signature(cfg.Twilio.AuthToken, config.RequestURL(req), req.PostForm) if !hmac.Equal([]byte(sig), calcSig) { - return errors.New("invalid X-Twilio-Signature") + if cfg.Twilio.AlternateAuthToken == "" { + return errors.New("invalid X-Twilio-Signature") + } + + calcSig = Signature(cfg.Twilio.AlternateAuthToken, config.RequestURL(req), req.PostForm) + if !hmac.Equal([]byte(sig), calcSig) { + return errors.New("invalid X-Twilio-Signature") + } } return nil diff --git a/web/src/schema.d.ts b/web/src/schema.d.ts index ce6ed69b77..f5d18276fc 100644 --- a/web/src/schema.d.ts +++ b/web/src/schema.d.ts @@ -1032,6 +1032,7 @@ type ConfigID = | 'Twilio.Enable' | 'Twilio.AccountSID' | 'Twilio.AuthToken' + | 'Twilio.AlternateAuthToken' | 'Twilio.FromNumber' | 'Twilio.MessagingServiceSID' | 'Twilio.DisableTwoWaySMS' From e0c80c84c0ab6eeb2cc38d33e95b1e6dc58decfd Mon Sep 17 00:00:00 2001 From: Nathaniel Caza Date: Wed, 24 Aug 2022 15:53:11 -0500 Subject: [PATCH 2/4] validate alt auth token --- config/config.go | 1 + 1 file changed, 1 insertion(+) diff --git a/config/config.go b/config/config.go index 7024c8fc12..1d1e41a8d4 100644 --- a/config/config.go +++ b/config/config.go @@ -430,6 +430,7 @@ func (cfg Config) Validate() error { validateKey("Slack.ClientSecret", cfg.Slack.ClientSecret), validateKey("Twilio.AccountSID", cfg.Twilio.AccountSID), validateKey("Twilio.AuthToken", cfg.Twilio.AuthToken), + validateKey("Twilio.AlternateAuthToken", cfg.Twilio.AlternateAuthToken), validateKey("GitHub.ClientID", cfg.GitHub.ClientID), validateKey("GitHub.ClientSecret", cfg.GitHub.ClientSecret), validateKey("Slack.AccessToken", cfg.Slack.AccessToken), From 2f609b26cea65f1fc5abaf15a12f8769ca4f05c7 Mon Sep 17 00:00:00 2001 From: Nathaniel Caza Date: Wed, 24 Aug 2022 15:56:16 -0500 Subject: [PATCH 3/4] update info to clairify usage --- config/config.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/config/config.go b/config/config.go index 1d1e41a8d4..20b2706cef 100644 --- a/config/config.go +++ b/config/config.go @@ -98,8 +98,8 @@ type Config struct { Enable bool `public:"true" info:"Enables sending and processing of Voice and SMS messages through the Twilio notification provider."` AccountSID string - AuthToken string `password:"true" info:"The primary Auth Token for Twilio. Must be primary Unless Alternate Auth Token is set."` - AlternateAuthToken string `password:"true" info:"An alternate Auth Token for validating requests. During a key change, set this to the current Primary, and Auth Token to Secondary, then promote and then clear this field."` + AuthToken string `password:"true" info:"The primary Auth Token for Twilio. Must be primary Unless Alternate Auth Token is set. This token is used for outgoing requests."` + AlternateAuthToken string `password:"true" info:"An alternate Auth Token for validating incoming requests. During a key change, set this to the Primary, and Auth Token to the Secondary, then promote and clear this field."` FromNumber string `public:"true" info:"The Twilio number to use for outgoing notifications."` From 8fe841600c5fc4ffc0c93c5233db55054f492241 Mon Sep 17 00:00:00 2001 From: Nathaniel Caza Date: Wed, 24 Aug 2022 16:19:11 -0500 Subject: [PATCH 4/4] regen mapconfig --- config/config.go | 2 +- graphql2/mapconfig.go | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/config/config.go b/config/config.go index 20b2706cef..bc29695435 100644 --- a/config/config.go +++ b/config/config.go @@ -98,7 +98,7 @@ type Config struct { Enable bool `public:"true" info:"Enables sending and processing of Voice and SMS messages through the Twilio notification provider."` AccountSID string - AuthToken string `password:"true" info:"The primary Auth Token for Twilio. Must be primary Unless Alternate Auth Token is set. This token is used for outgoing requests."` + AuthToken string `password:"true" info:"The primary Auth Token for Twilio. Must be primary unless Alternate Auth Token is set. This token is used for outgoing requests."` AlternateAuthToken string `password:"true" info:"An alternate Auth Token for validating incoming requests. During a key change, set this to the Primary, and Auth Token to the Secondary, then promote and clear this field."` FromNumber string `public:"true" info:"The Twilio number to use for outgoing notifications."` diff --git a/graphql2/mapconfig.go b/graphql2/mapconfig.go index 67de5aa876..85a8bd35fe 100644 --- a/graphql2/mapconfig.go +++ b/graphql2/mapconfig.go @@ -67,8 +67,8 @@ func MapConfigValues(cfg config.Config) []ConfigValue { {ID: "Slack.InteractiveMessages", Type: ConfigTypeBoolean, Description: "Enable interactive messages (e.g. buttons).", Value: fmt.Sprintf("%t", cfg.Slack.InteractiveMessages)}, {ID: "Twilio.Enable", Type: ConfigTypeBoolean, Description: "Enables sending and processing of Voice and SMS messages through the Twilio notification provider.", Value: fmt.Sprintf("%t", cfg.Twilio.Enable)}, {ID: "Twilio.AccountSID", Type: ConfigTypeString, Description: "", Value: cfg.Twilio.AccountSID}, - {ID: "Twilio.AuthToken", Type: ConfigTypeString, Description: "The primary Auth Token for Twilio. Must be primary Unless Alternate Auth Token is set.", Value: cfg.Twilio.AuthToken, Password: true}, - {ID: "Twilio.AlternateAuthToken", Type: ConfigTypeString, Description: "An alternate Auth Token for validating requests. During a key change, set this to the current Primary, and Auth Token to Secondary, then promote and then clear this field.", Value: cfg.Twilio.AlternateAuthToken, Password: true}, + {ID: "Twilio.AuthToken", Type: ConfigTypeString, Description: "The primary Auth Token for Twilio. Must be primary unless Alternate Auth Token is set. This token is used for outgoing requests.", Value: cfg.Twilio.AuthToken, Password: true}, + {ID: "Twilio.AlternateAuthToken", Type: ConfigTypeString, Description: "An alternate Auth Token for validating incoming requests. During a key change, set this to the Primary, and Auth Token to the Secondary, then promote and clear this field.", Value: cfg.Twilio.AlternateAuthToken, Password: true}, {ID: "Twilio.FromNumber", Type: ConfigTypeString, Description: "The Twilio number to use for outgoing notifications.", Value: cfg.Twilio.FromNumber}, {ID: "Twilio.MessagingServiceSID", Type: ConfigTypeString, Description: "If set, replaces the use of From Number for SMS notifications.", Value: cfg.Twilio.MessagingServiceSID}, {ID: "Twilio.DisableTwoWaySMS", Type: ConfigTypeBoolean, Description: "Disables SMS reply codes for alert messages.", Value: fmt.Sprintf("%t", cfg.Twilio.DisableTwoWaySMS)},