github.com/massongit/reviewdog@v0.0.0-20240331071725-4a16675475a8/doghouse/server/ciutil/ciutil.go (about) 1 package ciutil 2 3 import ( 4 "encoding/json" 5 "fmt" 6 "net" 7 "net/http" 8 "strings" 9 "sync" 10 ) 11 12 var ( 13 // Set Travis CI addrs by default though UpdateTravisCIIPAddrs will update it 14 // with latest one. 15 // $ dig +short nat.travisci.net | sort 16 // # Updated on 2018-06-03. 17 muTravisIPAddrs sync.RWMutex 18 travisIPAddrs = map[string]bool{ 19 "104.154.113.151": true, 20 "104.154.120.187": true, 21 "104.197.236.150": true, 22 "146.148.51.141": true, 23 "146.148.58.237": true, 24 "147.75.192.163": true, 25 "207.254.16.35": true, 26 "207.254.16.36": true, 27 "207.254.16.37": true, 28 "207.254.16.38": true, 29 "207.254.16.39": true, 30 "34.233.56.198": true, 31 "34.234.4.53": true, 32 "35.184.226.236": true, 33 "35.184.48.144": true, 34 "35.184.96.71": true, 35 "35.188.184.134": true, 36 "35.188.1.99": true, 37 "35.188.73.34": true, 38 "35.192.136.167": true, 39 "35.192.187.174": true, 40 "35.192.19.50": true, 41 "35.192.217.12": true, 42 "35.192.85.2": true, 43 "35.193.203.142": true, 44 "35.193.211.2": true, 45 "35.193.7.13": true, 46 "35.202.145.110": true, 47 "35.202.68.136": true, 48 "35.202.78.106": true, 49 "35.224.112.202": true, 50 "35.226.126.204": true, 51 "52.3.55.28": true, 52 "52.45.185.117": true, 53 "52.45.220.64": true, 54 "52.54.31.11": true, 55 "52.54.40.118": true, 56 "54.208.31.17": true, 57 } 58 59 // https://www.appveyor.com/docs/build-environment/#ip-addresses 60 appveyorIPAddrs = map[string]bool{ 61 "74.205.54.20": true, 62 "104.197.110.30": true, 63 "104.197.145.181": true, 64 "146.148.85.29": true, 65 "67.225.139.254": true, 66 "67.225.138.82": true, 67 "67.225.139.144": true, 68 "138.91.141.243": true, 69 } 70 ) 71 72 // IsFromCI returns true if given request is from trusted CI provider. 73 func IsFromCI(r *http.Request) bool { 74 return IsFromTravisCI(r) || IsFromAppveyor(r) 75 } 76 77 // IsFromTravisCI returns true if given request is from Travis CI. 78 // https://docs.travis-ci.com/user/ip-addresses/ 79 func IsFromTravisCI(r *http.Request) bool { 80 muTravisIPAddrs.RLock() 81 defer muTravisIPAddrs.RUnlock() 82 return travisIPAddrs[IPFromReq(r)] 83 } 84 85 // https://docs.travis-ci.com/user/ip-addresses/ 86 func UpdateTravisCIIPAddrs(cli *http.Client) error { 87 ips, err := ipAddrs("nat.travisci.net", cli) 88 if err != nil { 89 return err 90 } 91 muTravisIPAddrs.Lock() 92 defer muTravisIPAddrs.Unlock() 93 travisIPAddrs = map[string]bool{} 94 for _, ip := range ips { 95 travisIPAddrs[ip] = true 96 } 97 return nil 98 } 99 100 // IsFromAppveyor returns true if given request is from Appveyor. 101 // https://www.appveyor.com/docs/build-environment/#ip-addresses 102 func IsFromAppveyor(r *http.Request) bool { 103 return appveyorIPAddrs[IPFromReq(r)] 104 } 105 106 func IPFromReq(r *http.Request) string { 107 if f := r.Header.Get("Forwarded"); f != "" { 108 for _, kv := range strings.Split(f, ";") { 109 if kvPair := strings.SplitN(kv, "=", 2); len(kvPair) == 2 && 110 strings.ToLower(strings.TrimSpace(kvPair[0])) == "for" { 111 return strings.Trim(kvPair[1], ` "`) 112 } 113 } 114 } 115 116 ip, _, err := net.SplitHostPort(r.RemoteAddr) 117 if err != nil { 118 return r.RemoteAddr 119 } 120 return ip 121 } 122 123 // Cannot use "github.com/miekg/dns" in Google App Engine. 124 // Use dnsjson.com instead as workaround. 125 func ipAddrs(target string, cli *http.Client) ([]string, error) { 126 url := fmt.Sprintf("https://dnsjson.com/%s/A.json", target) 127 c := http.DefaultClient 128 if cli != nil { 129 c = cli 130 } 131 r, err := c.Get(url) 132 if err != nil { 133 return nil, err 134 } 135 defer r.Body.Close() 136 137 var res struct { 138 Results struct { 139 Records []string `json:"records"` 140 } `json:"results"` 141 } 142 143 if err := json.NewDecoder(r.Body).Decode(&res); err != nil { 144 return nil, err 145 } 146 147 if len(res.Results.Records) == 0 { 148 return nil, fmt.Errorf("failed to get IP addresses of %s", target) 149 } 150 151 return res.Results.Records, nil 152 }