github.com/cilium/cilium@v1.16.2/pkg/policy/api/http.go (about)

     1  // SPDX-License-Identifier: Apache-2.0
     2  // Copyright Authors of Cilium
     3  
     4  package api
     5  
     6  import (
     7  	"fmt"
     8  	"regexp"
     9  )
    10  
    11  // MismatchAction specifies what to do when there is no header match
    12  // Empty string is the default for making the rule to fail the match.
    13  // Otherwise the rule is still considered as matching, but the mismatches
    14  // are logged in the access log.
    15  type MismatchAction string
    16  
    17  const (
    18  	MismatchActionLog     MismatchAction = "LOG"     // Keep checking other matches
    19  	MismatchActionAdd     MismatchAction = "ADD"     // Add the missing value to a possibly multi-valued header
    20  	MismatchActionDelete  MismatchAction = "DELETE"  // Remove the whole mismatching header
    21  	MismatchActionReplace MismatchAction = "REPLACE" // Replace (of add if missing) the header
    22  )
    23  
    24  // HeaderMatch extends the HeaderValue for matching requirement of a
    25  // named header field against an immediate string, a secret value, or
    26  // a regex.  If none of the optional fields is present, then the
    27  // header value is not matched, only presence of the header is enough.
    28  type HeaderMatch struct {
    29  	// Mismatch identifies what to do in case there is no match. The default is
    30  	// to drop the request. Otherwise the overall rule is still considered as
    31  	// matching, but the mismatches are logged in the access log.
    32  	//
    33  	// +kubebuilder:validation:Enum=LOG;ADD;DELETE;REPLACE
    34  	// +kubebuilder:validation:Optional
    35  	Mismatch MismatchAction `json:"mismatch,omitempty"`
    36  
    37  	// Name identifies the header.
    38  	// +kubebuilder:validation:Required
    39  	// +kubebuilder:validation:MinLength=1
    40  	Name string `json:"name"`
    41  
    42  	// Secret refers to a secret that contains the value to be matched against.
    43  	// The secret must only contain one entry. If the referred secret does not
    44  	// exist, and there is no "Value" specified, the match will fail.
    45  	//
    46  	// +kubebuilder:validation:Optional
    47  	Secret *Secret `json:"secret,omitempty"`
    48  
    49  	// Value matches the exact value of the header. Can be specified either
    50  	// alone or together with "Secret"; will be used as the header value if the
    51  	// secret can not be found in the latter case.
    52  	//
    53  	// +kubebuilder:validation:Optional
    54  	Value string `json:"value,omitempty"`
    55  }
    56  
    57  // PortRuleHTTP is a list of HTTP protocol constraints. All fields are
    58  // optional, if all fields are empty or missing, the rule does not have any
    59  // effect.
    60  //
    61  // All fields of this type are extended POSIX regex as defined by IEEE Std
    62  // 1003.1, (i.e this follows the egrep/unix syntax, not the perl syntax)
    63  // matched against the path of an incoming request. Currently it can contain
    64  // characters disallowed from the conventional "path" part of a URL as defined
    65  // by RFC 3986.
    66  type PortRuleHTTP struct {
    67  	// Path is an extended POSIX regex matched against the path of a
    68  	// request. Currently it can contain characters disallowed from the
    69  	// conventional "path" part of a URL as defined by RFC 3986.
    70  	//
    71  	// If omitted or empty, all paths are all allowed.
    72  	//
    73  	// +kubebuilder:validation:Optional
    74  	Path string `json:"path,omitempty"`
    75  
    76  	// Method is an extended POSIX regex matched against the method of a
    77  	// request, e.g. "GET", "POST", "PUT", "PATCH", "DELETE", ...
    78  	//
    79  	// If omitted or empty, all methods are allowed.
    80  	//
    81  	// +kubebuilder:validation:Optional
    82  	Method string `json:"method,omitempty"`
    83  
    84  	// Host is an extended POSIX regex matched against the host header of a
    85  	// request. Examples:
    86  	//
    87  	// - foo.bar.com will match the host fooXbar.com or foo-bar.com
    88  	// - foo\.bar\.com will only match the host foo.bar.com
    89  	//
    90  	// If omitted or empty, the value of the host header is ignored.
    91  	//
    92  	// +kubebuilder:validation:Format=idn-hostname
    93  	// +kubebuilder:validation:Optional
    94  	Host string `json:"host,omitempty"`
    95  
    96  	// Headers is a list of HTTP headers which must be present in the
    97  	// request. If omitted or empty, requests are allowed regardless of
    98  	// headers present.
    99  	//
   100  	// +kubebuilder:validation:Optional
   101  	Headers []string `json:"headers,omitempty"`
   102  
   103  	// HeaderMatches is a list of HTTP headers which must be
   104  	// present and match against the given values. Mismatch field can be used
   105  	// to specify what to do when there is no match.
   106  	//
   107  	// +kubebuilder:validation:Optional
   108  	HeaderMatches []*HeaderMatch `json:"headerMatches,omitempty"`
   109  }
   110  
   111  // Sanitize sanitizes HTTP rules. It ensures that the path and method fields
   112  // are valid regular expressions. Note that the proxy may support a wider-range
   113  // of regular expressions (e.g. that specified by ECMAScript), so this function
   114  // may return some false positives. If the rule is invalid, returns an error.
   115  func (h *PortRuleHTTP) Sanitize() error {
   116  
   117  	if h.Path != "" {
   118  		_, err := regexp.Compile(h.Path)
   119  		if err != nil {
   120  			return err
   121  		}
   122  	}
   123  
   124  	if h.Method != "" {
   125  		_, err := regexp.Compile(h.Method)
   126  		if err != nil {
   127  			return err
   128  		}
   129  	}
   130  
   131  	// Headers are not sanitized.
   132  
   133  	// But HeaderMatches are
   134  	for _, m := range h.HeaderMatches {
   135  		if m.Name == "" {
   136  			return fmt.Errorf("Header name missing")
   137  		}
   138  		if m.Mismatch != "" &&
   139  			m.Mismatch != MismatchActionLog && m.Mismatch != MismatchActionAdd &&
   140  			m.Mismatch != MismatchActionDelete && m.Mismatch != MismatchActionReplace {
   141  			return fmt.Errorf("Invalid header action: %s", m.Mismatch)
   142  		}
   143  		if m.Secret != nil && m.Secret.Name == "" {
   144  			return fmt.Errorf("Secret name missing")
   145  		}
   146  	}
   147  
   148  	return nil
   149  }