diff --git a/services/federation/main.go b/services/federation/main.go index a411216c3d..efcc3186a0 100644 --- a/services/federation/main.go +++ b/services/federation/main.go @@ -30,8 +30,8 @@ type Config struct { ReverseFederation string `toml:"reverse-federation" valid:"optional"` } `valid:"required"` TLS struct { - CertificateFile string `toml:"certificate-file"` - PrivateKeyFile string `toml:"private-key-file"` + CertificateFile string `toml:"certificate-file" valid:"optional"` + PrivateKeyFile string `toml:"private-key-file" valid:"optional"` } `valid:"optional"` } diff --git a/support/config/main.go b/support/config/main.go index 60234c4213..df408c5fac 100644 --- a/support/config/main.go +++ b/support/config/main.go @@ -3,6 +3,9 @@ package config import ( + "fmt" + "io/ioutil" + "github.com/BurntSushi/toml" "github.com/asaskevich/govalidator" "github.com/stellar/go/strkey" @@ -18,11 +21,26 @@ type InvalidConfigError struct { // Read takes the TOML configuration file at `path`, parses it into `dest` and // then uses github.com/asaskevich/govalidator to validate the struct. func Read(path string, dest interface{}) error { - _, err := toml.DecodeFile(path, dest) + bs, err := ioutil.ReadFile(path) + if err != nil { + return err + } + return decode(string(bs), dest) +} + +func decode(content string, dest interface{}) error { + metadata, err := toml.Decode(content, dest) if err != nil { return errors.Wrap(err, "decode-file failed") } + // Undecoded keys correspond to keys in the TOML document + // that do not have a concrete type in config struct. + undecoded := metadata.Undecoded() + if len(undecoded) > 0 { + return errors.New("Unknown fields: " + fmt.Sprintf("%+v", undecoded)) + } + valid, err := govalidator.ValidateStruct(dest) if valid { diff --git a/support/config/main_test.go b/support/config/main_test.go index a57e01e8e0..fc870f81e4 100644 --- a/support/config/main_test.go +++ b/support/config/main_test.go @@ -83,3 +83,42 @@ func TestSeedValidator(t *testing.T) { _, ok = fields["WrongType"] assert.True(t, ok, "WrongType is not an invalid field") } + +func TestUndecoded(t *testing.T) { + var val struct { + Test string `toml:"test" valid:"optional"` + TLS struct { + CertificateFile string `toml:"certificate-file" valid:"optional"` + PrivateKeyFile string `toml:"private-key-file" valid:"optional"` + } `valid:"optional"` + } + + // Notice _ in certificate_file + toml := `test="abc" +[tls] +certificate_file="hello" +private-key-file="world"` + + err := decode(toml, &val) + require.Error(t, err) + assert.Equal(t, "Unknown fields: [tls.certificate_file]", err.Error()) +} + +func TestCorrect(t *testing.T) { + var val struct { + Test string `toml:"test" valid:"optional"` + TLS struct { + CertificateFile string `toml:"certificate-file" valid:"optional"` + PrivateKeyFile string `toml:"private-key-file" valid:"optional"` + } `valid:"optional"` + } + + // Notice _ in certificate_file + toml := `test="abc" +[tls] +certificate-file="hello" +private-key-file="world"` + + err := decode(toml, &val) + require.NoError(t, err) +}