github.com/letsencrypt/boulder@v0.20251208.0/observer/probers/http/http_conf.go (about) 1 package probers 2 3 import ( 4 "fmt" 5 "net/url" 6 7 "github.com/letsencrypt/boulder/observer/probers" 8 "github.com/letsencrypt/boulder/strictyaml" 9 "github.com/prometheus/client_golang/prometheus" 10 ) 11 12 // HTTPConf is exported to receive YAML configuration. 13 type HTTPConf struct { 14 URL string `yaml:"url"` 15 RCodes []int `yaml:"rcodes"` 16 UserAgent string `yaml:"useragent"` 17 Insecure bool `yaml:"insecure"` 18 } 19 20 // Kind returns a name that uniquely identifies the `Kind` of `Configurer`. 21 func (c HTTPConf) Kind() string { 22 return "HTTP" 23 } 24 25 // UnmarshalSettings takes YAML as bytes and unmarshals it to the to an 26 // HTTPConf object. 27 func (c HTTPConf) UnmarshalSettings(settings []byte) (probers.Configurer, error) { 28 var conf HTTPConf 29 err := strictyaml.Unmarshal(settings, &conf) 30 if err != nil { 31 return nil, err 32 } 33 return conf, nil 34 } 35 36 func (c HTTPConf) validateURL() error { 37 url, err := url.Parse(c.URL) 38 if err != nil { 39 return fmt.Errorf( 40 "invalid 'url', got: %q, expected a valid url", c.URL) 41 } 42 if url.Scheme == "" { 43 return fmt.Errorf( 44 "invalid 'url', got: %q, missing scheme", c.URL) 45 } 46 return nil 47 } 48 49 func (c HTTPConf) validateRCodes() error { 50 if len(c.RCodes) == 0 { 51 return fmt.Errorf( 52 "invalid 'rcodes', got: %q, please specify at least one", c.RCodes) 53 } 54 for _, c := range c.RCodes { 55 // ensure rcode entry is in range 100-599 56 if c < 100 || c > 599 { 57 return fmt.Errorf( 58 "'rcodes' contains an invalid HTTP response code, '%d'", c) 59 } 60 } 61 return nil 62 } 63 64 // MakeProber constructs a `HTTPProbe` object from the contents of the 65 // bound `HTTPConf` object. If the `HTTPConf` cannot be validated, an 66 // error appropriate for end-user consumption is returned instead. 67 func (c HTTPConf) MakeProber(_ map[string]prometheus.Collector) (probers.Prober, error) { 68 // validate `url` 69 err := c.validateURL() 70 if err != nil { 71 return nil, err 72 } 73 74 // validate `rcodes` 75 err = c.validateRCodes() 76 if err != nil { 77 return nil, err 78 } 79 80 // Set default User-Agent if none set. 81 if c.UserAgent == "" { 82 c.UserAgent = "letsencrypt/boulder-observer-http-client" 83 } 84 return HTTPProbe{c.URL, c.RCodes, c.UserAgent, c.Insecure}, nil 85 } 86 87 // Instrument is a no-op to implement the `Configurer` interface. 88 func (c HTTPConf) Instrument() map[string]prometheus.Collector { 89 return nil 90 } 91 92 // init is called at runtime and registers `HTTPConf`, a `Prober` 93 // `Configurer` type, as "HTTP". 94 func init() { 95 probers.Register(HTTPConf{}) 96 }