github.com/pf-qiu/concourse/v6@v6.7.3-0.20201207032516-1f455d73275f/atc/api/policychecker/checker.go (about)

     1  package policychecker
     2  
     3  import (
     4  	"bytes"
     5  	"encoding/json"
     6  	"io/ioutil"
     7  	"net/http"
     8  
     9  	"sigs.k8s.io/yaml"
    10  
    11  	"github.com/pf-qiu/concourse/v6/atc/api/accessor"
    12  	"github.com/pf-qiu/concourse/v6/atc/policy"
    13  )
    14  
    15  //go:generate counterfeiter . PolicyChecker
    16  
    17  type PolicyChecker interface {
    18  	Check(string, accessor.Access, *http.Request) (policy.PolicyCheckOutput, error)
    19  }
    20  
    21  type checker struct {
    22  	policyChecker policy.Checker
    23  }
    24  
    25  func NewApiPolicyChecker(policyChecker policy.Checker) PolicyChecker {
    26  	return &checker{policyChecker: policyChecker}
    27  }
    28  
    29  func (c *checker) Check(action string, acc accessor.Access, req *http.Request) (policy.PolicyCheckOutput, error) {
    30  	// Ignore self invoked API calls.
    31  	if acc.IsSystem() {
    32  		return policy.PassedPolicyCheck(), nil
    33  	}
    34  
    35  	// Actions in black will not go through policy check.
    36  	if c.policyChecker.ShouldSkipAction(action) {
    37  		return policy.PassedPolicyCheck(), nil
    38  	}
    39  
    40  	// Only actions with specified http method will go through policy check.
    41  	// But actions in white list will always go through policy check.
    42  	if !c.policyChecker.ShouldCheckHttpMethod(req.Method) &&
    43  		!c.policyChecker.ShouldCheckAction(action) {
    44  		return policy.PassedPolicyCheck(), nil
    45  	}
    46  
    47  	team := req.FormValue(":team_name")
    48  	input := policy.PolicyCheckInput{
    49  		HttpMethod: req.Method,
    50  		Action:     action,
    51  		User:       acc.Claims().UserName,
    52  		Roles:      acc.TeamRoles()[team],
    53  		Team:       team,
    54  		Pipeline:   req.FormValue(":pipeline_name"),
    55  	}
    56  
    57  	switch ct := req.Header.Get("Content-type"); ct {
    58  	case "application/json", "text/vnd.yaml", "text/yaml", "text/x-yaml", "application/x-yaml":
    59  		body, err := ioutil.ReadAll(req.Body)
    60  		if err != nil {
    61  			return policy.FailedPolicyCheck(), err
    62  		} else if body != nil && len(body) > 0 {
    63  			if ct == "application/json" {
    64  				err = json.Unmarshal(body, &input.Data)
    65  			} else {
    66  				err = yaml.Unmarshal(body, &input.Data)
    67  			}
    68  			if err != nil {
    69  				return policy.FailedPolicyCheck(), err
    70  			}
    71  
    72  			req.Body = ioutil.NopCloser(bytes.NewBuffer(body))
    73  		}
    74  	}
    75  
    76  	return c.policyChecker.Check(input)
    77  }