config: enforce HTTP or HTTPS URLs (#1567)

Signed-off-by: Simon Pasquier <spasquie@redhat.com>
This commit is contained in:
Simon Pasquier 2018-10-05 19:29:52 +02:00 committed by stuart nelson
parent e6c5c03c9e
commit ce2f2ac380
3 changed files with 46 additions and 17 deletions

View File

@ -51,7 +51,7 @@ func (s Secret) MarshalJSON() ([]byte, error) {
return json.Marshal("<secret>")
}
// URL is a custom type that allows validation at configuration load time.
// URL is a custom type that represents an HTTP or HTTPS URL and allows validation at configuration load time.
type URL struct {
*url.URL
}
@ -76,11 +76,11 @@ func (u *URL) UnmarshalYAML(unmarshal func(interface{}) error) error {
if err := unmarshal(&s); err != nil {
return err
}
urlp, err := url.Parse(s)
urlp, err := parseURL(s)
if err != nil {
return err
}
u.URL = urlp
u.URL = urlp.URL
return nil
}
@ -98,11 +98,11 @@ func (u *URL) UnmarshalJSON(data []byte) error {
if err := json.Unmarshal(data, &s); err != nil {
return err
}
urlp, err := url.Parse(s)
urlp, err := parseURL(s)
if err != nil {
return err
}
u.URL = urlp
u.URL = urlp.URL
return nil
}
@ -434,11 +434,25 @@ var DefaultGlobalConfig = GlobalConfig{
}
func mustParseURL(s string) *URL {
u, err := url.Parse(s)
u, err := parseURL(s)
if err != nil {
panic(err)
}
return &URL{u}
return u
}
func parseURL(s string) (*URL, error) {
u, err := url.Parse(s)
if err != nil {
return nil, err
}
if u.Scheme != "http" && u.Scheme != "https" {
return nil, fmt.Errorf("unsupported scheme %q for URL", u.Scheme)
}
if u.Host == "" {
return nil, fmt.Errorf("missing host for URL")
}
return &URL{u}, nil
}
// GlobalConfig defines configuration parameters that are valid globally

View File

@ -369,7 +369,28 @@ func TestUnmarshalURL(t *testing.T) {
}
func TestUnmarshalInvalidURL(t *testing.T) {
b := []byte(`"://example.com"`)
for _, b := range [][]byte{
[]byte(`"://example.com"`),
[]byte(`"http:example.com"`),
[]byte(`"telnet://example.com"`),
} {
var u URL
err := json.Unmarshal(b, &u)
if err == nil {
t.Errorf("Expected an error unmarshalling %q from JSON", string(b))
}
err = yaml.Unmarshal(b, &u)
if err == nil {
t.Errorf("Expected an error unmarshalling %q from YAML", string(b))
}
t.Logf("%s", err)
}
}
func TestUnmarshalRelativeURL(t *testing.T) {
b := []byte(`"/home"`)
var u URL
err := json.Unmarshal(b, &u)
@ -383,22 +404,16 @@ func TestUnmarshalInvalidURL(t *testing.T) {
}
}
func TestJSONUnmarshalMarshaled(t *testing.T) {
func TestJSONUnmarshal(t *testing.T) {
c, _, err := LoadFile("testdata/conf.good.yml")
if err != nil {
t.Errorf("Error parsing %s: %s", "testdata/conf.good.yml", err)
}
plainCfg, err := json.Marshal(c)
_, err = json.Marshal(c)
if err != nil {
t.Fatal("JSON Marshaling failed:", err)
}
cfg := Config{}
err = json.Unmarshal(plainCfg, &cfg)
if err != nil {
t.Fatal("JSON Unmarshaling failed:", err)
}
}
func TestEmptyFieldsAndRegex(t *testing.T) {

View File

@ -6,7 +6,7 @@ global:
smtp_hello: ''
hipchat_auth_token: 'mysecret'
hipchat_api_url: 'https://hipchat.foobar.org/'
slack_api_url: 'mysecret'
slack_api_url: 'https://slack.com/webhook'