SSHSecure/config/validator.go

168 lines
4.3 KiB
Go

package config
import (
`errors`
`fmt`
`reflect`
`strings`
)
var err error
// TODO: Match block validation
// Have I mentioned how dumb golang is yet? The following methods share 90% of the same code,
// but ironically delegating that to a separate function is going to be even more of a PITA for now
// than just maintaining two separate methods.
// How dumb.
// Validate validates the actual struct of an SshdConf itself, ensuring that certain list fields contain
// valid item(s). It collects all found issues in allErr.
func (c *SshdConf) Validate() (validConf bool, allErr []error) {
// Set the default as true.
// We set it on false on first failed validation and keep going.
validConf = true
fields := reflect.TypeOf(c)
values := reflect.ValueOf(c)
for i := 0; i < fields.NumField(); i++ {
field := fields.Field(i)
value := values.Field(i)
var validField bool
n := field.Name
single, isSingle := validSshdSingleVals[n]
multi, isMulti := validSshdMultiVals[n]
if isSingle {
v := value.String()
for _, x := range single {
if v == x {
validField = true
break
}
}
if !validField {
validConf = false
e := fmt.Sprintf(
"field %v: value %v is not allowed; must be ONE of: %v",
n, v, single,
)
allErr = append(allErr, errors.New(e))
}
} else if isMulti {
// These are all []strings if the field name is in validSshdMultiVals.
// But golang is still dumb and has no way of serializing directly, so here comes the hackery.
v, ok := value.Interface().([]string)
if !ok {
validConf = false
e := fmt.Sprintf(
"field %v: value %v was not able to be parsed as a []string",
n, v,
)
allErr = append(allErr, errors.New(e))
}
var invalidSlice []string
for _, vStr := range v {
validItem := false
for _, strip := range sshdStripPre {
if n == strip {
for _, c := range []string{"+", "-", "^"} {
vStr = strings.TrimPrefix(vStr, c)
}
}
}
for _, x := range multi {
if vStr == x {
validItem = true
}
}
if !validItem {
invalidSlice = append(invalidSlice, vStr)
}
}
for _, x := range invalidSlice {
e := fmt.Sprintf(
"field %v: value item %v is not valid; it must be one or more of %v",
n, x, multi,
)
allErr = append(allErr, errors.New(e))
}
}
}
return validConf, allErr
}
// Validate validates the actual struct of an SshConf itself, ensuring that certain list fields contain
// valid item(s). It collects all found issues in allErr.
func (c *SshConf) Validate() (validConf bool, allErr []error) {
// Set the default as true.
// We set it on false on first failed validation and keep going.
validConf = true
fields := reflect.TypeOf(c)
values := reflect.ValueOf(c)
for i := 0; i < fields.NumField(); i++ {
field := fields.Field(i)
value := values.Field(i)
var validField bool
n := field.Name
single, isSingle := validSshSingleVals[n]
multi, isMulti := validSshMultiVals[n]
if isSingle {
v := value.String()
for _, x := range single {
if v == x {
validField = true
break
}
}
if !validField {
validConf = false
e := fmt.Sprintf(
"field %v: value %v is not allowed; must be ONE of: %v",
n, v, single,
)
allErr = append(allErr, errors.New(e))
}
} else if isMulti {
// These are all []strings if the field name is in validSshMultiVals.
// But golang is still dumb and has no way of serializing directly, so here comes the hackery.
v, ok := value.Interface().([]string)
if !ok {
validConf = false
e := fmt.Sprintf(
"field %v: value %v was not able to be parsed as a []string",
n, v,
)
allErr = append(allErr, errors.New(e))
}
var invalidSlice []string
for _, vStr := range v {
validItem := false
for _, strip := range sshStripPre {
if n == strip {
for _, c := range []string{"+", "-", "^"} {
vStr = strings.TrimPrefix(vStr, c)
}
}
}
for _, x := range multi {
if vStr == x {
validItem = true
}
}
if !validItem {
invalidSlice = append(invalidSlice, vStr)
}
}
for _, x := range invalidSlice {
e := fmt.Sprintf(
"field %v: value item %v is not valid; it must be one or more of %v",
n, x, multi,
)
allErr = append(allErr, errors.New(e))
}
}
}
return validConf, allErr
}