@@ -25,10 +25,12 @@ import (
2525 "encoding/xml"
2626 "fmt"
2727 "io"
28+ "net"
2829 "net/http"
2930 "net/url"
3031 "reflect"
3132 "regexp"
33+ "strings"
3234 "sync"
3335 "time"
3436 "unicode/utf8"
@@ -43,9 +45,13 @@ import (
4345
4446// ErrIgnoreAndContinue is a error which should be ignored
4547var (
46- ErrIgnoreAndContinue = errors .Default .New ("ignore and continue" )
47- ErrEmptyResponse = errors .Default .New ("empty response" )
48- _ plugin.ApiClient = (* ApiClient )(nil )
48+ ErrIgnoreAndContinue = errors .Default .New ("ignore and continue" )
49+ ErrEmptyResponse = errors .Default .New ("empty response" )
50+ ErrRedirectionNotAllowed = errors .BadInput .New ("redirection is not allowed" )
51+ ErrInvalidURL = errors .Default .New ("Invalid URL" )
52+ ErrInvalidCIDR = errors .Default .New ("Invalid CIDR" )
53+ ErrHostNotAllowed = errors .Default .New ("Host is not allowed" )
54+ _ plugin.ApiClient = (* ApiClient )(nil )
4955)
5056
5157// ApiClient is designed for simple api requests
@@ -103,6 +109,18 @@ func NewApiClient(
103109 proxy string ,
104110 br context.BasicRes ,
105111) (* ApiClient , errors.Error ) {
112+ cfg := br .GetConfigReader ()
113+ log := br .GetLogger ()
114+
115+ // endpoint blacklist
116+ endpointCidrBlacklist := cfg .GetString ("ENDPOINT_CIDR_BLACKLIST" )
117+ if endpointCidrBlacklist != "" {
118+ err := checkCidrBlacklist (endpointCidrBlacklist , endpoint , log )
119+ if err != nil {
120+ return nil , err
121+ }
122+ }
123+
106124 apiClient := & ApiClient {}
107125 apiClient .Setup (
108126 endpoint ,
@@ -113,7 +131,7 @@ func NewApiClient(
113131 apiClient .client .Transport = & http.Transport {}
114132
115133 // set insecureSkipVerify
116- insecureSkipVerify := br . GetConfigReader () .GetBool ("IN_SECURE_SKIP_VERIFY" )
134+ insecureSkipVerify := cfg .GetBool ("IN_SECURE_SKIP_VERIFY" )
117135 if insecureSkipVerify {
118136 apiClient .client .Transport .(* http.Transport ).TLSClientConfig = & tls.Config {InsecureSkipVerify : true }
119137 }
@@ -155,6 +173,14 @@ func NewApiClient(
155173 }
156174 apiClient .SetContext (ctx )
157175
176+ // apply global security settings
177+ forbidRedirection := cfg .GetBool ("FORBID_REDIRECTION" )
178+ if forbidRedirection {
179+ apiClient .client .CheckRedirect = func (req * http.Request , via []* http.Request ) error {
180+ return ErrRedirectionNotAllowed
181+ }
182+ }
183+
158184 return apiClient , nil
159185}
160186
@@ -454,3 +480,35 @@ func RemoveStartingSlashFromPath(relativePath string) string {
454480 }
455481 return relativePath
456482}
483+
484+ func checkCidrBlacklist (blacklist , endpoint string , log log.Logger ) errors.Error {
485+ // only if blacklist is given and the host of the endpoint is an IP address
486+ parsedEp , err := url .Parse (endpoint )
487+ if err != nil {
488+ return ErrInvalidURL
489+ }
490+ endpointHost := parsedEp .Hostname ()
491+ if endpointHost == "" {
492+ return ErrInvalidURL
493+ }
494+ endpointIp := net .ParseIP (endpointHost )
495+ if endpointIp != nil {
496+ // check if the IP is in the blacklist
497+ cidrs := strings .Split (blacklist , "," )
498+ for _ , cidr := range cidrs {
499+ // CIDR format : 10.0.0.1/24
500+ // check the net.ParseCIDR for details
501+ cidr = strings .TrimSpace (cidr )
502+ _ , ipnet , err := net .ParseCIDR (cidr )
503+ if err != nil {
504+ // the CIDR is invalid
505+ log .Error (err , "Invalid CIDR" , "cidr" , cidr )
506+ return ErrInvalidCIDR
507+ }
508+ if ipnet .Contains (endpointIp ) {
509+ return ErrHostNotAllowed
510+ }
511+ }
512+ }
513+ return nil
514+ }
0 commit comments