Files
atlantis/server/controllers/events/github_request_validator.go
Eng Zer Jun 38cf7b0141 refactor: move from io/ioutil to io and os package (#1843)
The io/ioutil package has been deprecated as of Go 1.16, see
https://golang.org/doc/go1.16#ioutil. This commit replaces the existing
io/ioutil functions with their new definitions in io and os packages.

Signed-off-by: Eng Zer Jun <engzerjun@gmail.com>
2021-10-07 00:37:42 -04:00

79 lines
2.8 KiB
Go

// Copyright 2017 HootSuite Media 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.
// Modified hereafter by contributors to runatlantis/atlantis.
package events
import (
"errors"
"fmt"
"io"
"net/http"
"github.com/google/go-github/v31/github"
)
//go:generate pegomock generate -m --use-experimental-model-gen --package mocks -o mocks/mock_github_request_validator.go GithubRequestValidator
// GithubRequestValidator handles checking if GitHub requests are signed
// properly by the secret.
type GithubRequestValidator interface {
// Validate returns the JSON payload of the request.
// If secret is not empty, it checks that the request was signed
// by secret and returns an error if it was not.
// If secret is empty, it does not check if the request was signed.
Validate(r *http.Request, secret []byte) ([]byte, error)
}
// DefaultGithubRequestValidator handles checking if GitHub requests are signed
// properly by the secret.
type DefaultGithubRequestValidator struct{}
// Validate returns the JSON payload of the request.
// If secret is not empty, it checks that the request was signed
// by secret and returns an error if it was not.
// If secret is empty, it does not check if the request was signed.
func (d *DefaultGithubRequestValidator) Validate(r *http.Request, secret []byte) ([]byte, error) {
if len(secret) != 0 {
return d.validateAgainstSecret(r, secret)
}
return d.validateWithoutSecret(r)
}
func (d *DefaultGithubRequestValidator) validateAgainstSecret(r *http.Request, secret []byte) ([]byte, error) {
payload, err := github.ValidatePayload(r, secret)
if err != nil {
return nil, err
}
return payload, nil
}
func (d *DefaultGithubRequestValidator) validateWithoutSecret(r *http.Request) ([]byte, error) {
switch ct := r.Header.Get("Content-Type"); ct {
case "application/json":
payload, err := io.ReadAll(r.Body)
if err != nil {
return nil, fmt.Errorf("could not read body: %s", err)
}
return payload, nil
case "application/x-www-form-urlencoded":
// GitHub stores the json payload as a form value.
payloadForm := r.FormValue("payload")
if payloadForm == "" {
return nil, errors.New("webhook request did not contain expected 'payload' form value")
}
return []byte(payloadForm), nil
default:
return nil, fmt.Errorf("webhook request has unsupported Content-Type %q", ct)
}
}