diff --git a/docs/content/en/docs-dev/operator-manual/piped/configuration-reference.md b/docs/content/en/docs-dev/operator-manual/piped/configuration-reference.md index 5513d36ec1..f8a2666f7f 100644 --- a/docs/content/en/docs-dev/operator-manual/piped/configuration-reference.md +++ b/docs/content/en/docs-dev/operator-manual/piped/configuration-reference.md @@ -248,3 +248,4 @@ Must be one of the following structs: | url | string | The URL where notification event will be sent to. | Yes | | signatureKey | string | The HTTP header key used to store the configured signature in each event. Default is "PipeCD-Signature". | No | | signatureValue | string | The value of signature included in header of each event request. It can be used to verify the received events. | No | +| signatureValueFile | string | The path to the signature value file. | No | diff --git a/pkg/app/piped/notifier/webhook.go b/pkg/app/piped/notifier/webhook.go index 32981ed670..b296b405b0 100644 --- a/pkg/app/piped/notifier/webhook.go +++ b/pkg/app/piped/notifier/webhook.go @@ -82,7 +82,13 @@ func (w *webhook) sendEvent(ctx context.Context, event model.NotificationEvent) return } - req.Header.Add(w.config.SignatureKey, w.config.SignatureValue) + signature, err := w.config.LoadSignatureValue() + if err != nil { + w.logger.Error("unable to load webhook signature value", zap.Error(err)) + return + } + + req.Header.Add(w.config.SignatureKey, signature) resp, err := w.httpClient.Do(req) if err != nil { diff --git a/pkg/config/piped.go b/pkg/config/piped.go index 8d51dd8d10..4426f3456e 100644 --- a/pkg/config/piped.go +++ b/pkg/config/piped.go @@ -20,6 +20,7 @@ import ( "errors" "fmt" "os" + "strings" "github.com/pipe-cd/pipecd/pkg/model" ) @@ -610,9 +611,27 @@ type NotificationReceiverSlack struct { } type NotificationReceiverWebhook struct { - URL string `json:"url"` - SignatureKey string `json:"signatureKey" default:"PipeCD-Signature"` - SignatureValue string `json:"signatureValue"` + URL string `json:"url"` + SignatureKey string `json:"signatureKey" default:"PipeCD-Signature"` + SignatureValue string `json:"signatureValue"` + SignatureValueFile string `json:"signatureValueFile"` +} + +func (n *NotificationReceiverWebhook) LoadSignatureValue() (string, error) { + if n.SignatureValue != "" && n.SignatureValueFile != "" { + return "", errors.New("only either signatureValue or signatureValueFile can be set") + } + if n.SignatureValue != "" { + return n.SignatureValue, nil + } + if n.SignatureValueFile != "" { + val, err := os.ReadFile(n.SignatureValueFile) + if err != nil { + return "", err + } + return strings.TrimSuffix(string(val), "\n"), nil + } + return "", nil } type SecretManagement struct { diff --git a/pkg/config/piped_test.go b/pkg/config/piped_test.go index c462c60044..cde3d6667c 100644 --- a/pkg/config/piped_test.go +++ b/pkg/config/piped_test.go @@ -319,3 +319,48 @@ func TestPipedEventWatcherValidate(t *testing.T) { }) } } + +func TestNotificationReceiverWebhook_LoadSignatureValue(t *testing.T) { + testcase := []struct { + name string + webhook *NotificationReceiverWebhook + want string + wantErr bool + }{ + { + name: "set signatureValue", + webhook: &NotificationReceiverWebhook{ + URL: "https://example.com", + SignatureValue: "foo", + }, + want: "foo", + wantErr: false, + }, + { + name: "set signatureValueFile", + webhook: &NotificationReceiverWebhook{ + URL: "https://example.com", + SignatureValueFile: "testdata/piped/notification-receiver-webhook", + }, + want: "foo", + wantErr: false, + }, + { + name: "set both of them", + webhook: &NotificationReceiverWebhook{ + URL: "https://example.com", + SignatureValue: "foo", + SignatureValueFile: "testdata/piped/notification-receiver-webhook", + }, + want: "", + wantErr: true, + }, + } + for _, tc := range testcase { + t.Run(tc.name, func(t *testing.T) { + got, err := tc.webhook.LoadSignatureValue() + assert.Equal(t, tc.wantErr, err != nil) + assert.Equal(t, tc.want, got) + }) + } +} diff --git a/pkg/config/testdata/piped/notification-receiver-webhook b/pkg/config/testdata/piped/notification-receiver-webhook new file mode 100644 index 0000000000..257cc5642c --- /dev/null +++ b/pkg/config/testdata/piped/notification-receiver-webhook @@ -0,0 +1 @@ +foo