config/validate: add rule for file paths
This commit is contained in:
parent
cc75a943ba
commit
bdbd1930ed
@ -18,7 +18,9 @@ package validate
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"path"
|
||||||
"reflect"
|
"reflect"
|
||||||
|
"strings"
|
||||||
|
|
||||||
"github.com/coreos/coreos-cloudinit/config"
|
"github.com/coreos/coreos-cloudinit/config"
|
||||||
)
|
)
|
||||||
@ -29,6 +31,7 @@ type rule func(config node, report *Report)
|
|||||||
var Rules []rule = []rule{
|
var Rules []rule = []rule{
|
||||||
checkStructure,
|
checkStructure,
|
||||||
checkValidity,
|
checkValidity,
|
||||||
|
checkWriteFiles,
|
||||||
}
|
}
|
||||||
|
|
||||||
// checkStructure compares the provided config to the empty config.CloudConfig
|
// checkStructure compares the provided config to the empty config.CloudConfig
|
||||||
@ -67,6 +70,24 @@ func checkNodeStructure(n, g node, r *Report) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// isCompatible determines if the type of kind n can be converted to the type
|
||||||
|
// of kind g in the context of YAML. This is not an exhaustive list, but its
|
||||||
|
// enough for the purposes of cloud-config validation.
|
||||||
|
func isCompatible(n, g reflect.Kind) bool {
|
||||||
|
switch g {
|
||||||
|
case reflect.String:
|
||||||
|
return n == reflect.String || n == reflect.Int || n == reflect.Float64 || n == reflect.Bool
|
||||||
|
case reflect.Struct:
|
||||||
|
return n == reflect.Struct || n == reflect.Map
|
||||||
|
case reflect.Float64:
|
||||||
|
return n == reflect.Float64 || n == reflect.Int
|
||||||
|
case reflect.Bool, reflect.Slice, reflect.Int:
|
||||||
|
return n == g
|
||||||
|
default:
|
||||||
|
panic(fmt.Sprintf("isCompatible(): unhandled kind %s", g))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// checkValidity checks the value of every node in the provided config by
|
// checkValidity checks the value of every node in the provided config by
|
||||||
// running config.AssertValid() on it.
|
// running config.AssertValid() on it.
|
||||||
func checkValidity(cfg node, report *Report) {
|
func checkValidity(cfg node, report *Report) {
|
||||||
@ -98,20 +119,20 @@ func checkNodeValidity(n, g node, r *Report) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// isCompatible determines if the type of kind n can be converted to the type
|
// checkWriteFiles checks to make sure that the target file can actually be
|
||||||
// of kind g in the context of YAML. This is not an exhaustive list, but its
|
// written. Note that this check is approximate (it only checks to see if the file
|
||||||
// enough for the purposes of cloud-config validation.
|
// is under /usr).
|
||||||
func isCompatible(n, g reflect.Kind) bool {
|
func checkWriteFiles(cfg node, report *Report) {
|
||||||
switch g {
|
for _, f := range cfg.Child("write_files").children {
|
||||||
case reflect.String:
|
c := f.Child("path")
|
||||||
return n == reflect.String || n == reflect.Int || n == reflect.Float64 || n == reflect.Bool
|
if !c.IsValid() {
|
||||||
case reflect.Struct:
|
continue
|
||||||
return n == reflect.Struct || n == reflect.Map
|
}
|
||||||
case reflect.Float64:
|
|
||||||
return n == reflect.Float64 || n == reflect.Int
|
d := path.Dir(c.String())
|
||||||
case reflect.Bool, reflect.Slice, reflect.Int:
|
switch {
|
||||||
return n == g
|
case strings.HasPrefix(d, "/usr"):
|
||||||
default:
|
report.Error(c.line, "file cannot be written to a read-only filesystem")
|
||||||
panic(fmt.Sprintf("isCompatible(): unhandled kind %s", g))
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -249,3 +249,40 @@ func TestCheckValidity(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestCheckWriteFiles(t *testing.T) {
|
||||||
|
tests := []struct {
|
||||||
|
config string
|
||||||
|
|
||||||
|
entries []Entry
|
||||||
|
}{
|
||||||
|
{},
|
||||||
|
{
|
||||||
|
config: "write_files:\n - path: /valid",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
config: "write_files:\n - path: /tmp/usr/valid",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
config: "write_files:\n - path: /usr/invalid",
|
||||||
|
entries: []Entry{{entryError, "file cannot be written to a read-only filesystem", 2}},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
config: "write-files:\n - path: /tmp/../usr/invalid",
|
||||||
|
entries: []Entry{{entryError, "file cannot be written to a read-only filesystem", 2}},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for i, tt := range tests {
|
||||||
|
r := Report{}
|
||||||
|
n, err := parseCloudConfig([]byte(tt.config), &r)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
checkWriteFiles(n, &r)
|
||||||
|
|
||||||
|
if e := r.Entries(); !reflect.DeepEqual(tt.entries, e) {
|
||||||
|
t.Errorf("bad report (%d, %q): want %#v, got %#v", i, tt.config, tt.entries, e)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user