diff --git a/internal/config/config.go b/internal/config/config.go index a18f7a2..d764939 100644 --- a/internal/config/config.go +++ b/internal/config/config.go @@ -20,6 +20,7 @@ var Keys schema.ProgramConfig = schema.ProgramConfig{ DB: "./var/job.db", Archive: json.RawMessage(`{\"kind\":\"file\",\"path\":\"./var/job-archive\"}`), DisableArchive: false, + Validate: false, LdapConfig: nil, SessionMaxAge: "168h", UiDefaults: map[string]interface{}{ diff --git a/pkg/archive/fsBackend.go b/pkg/archive/fsBackend.go index 9a54622..80352a4 100644 --- a/pkg/archive/fsBackend.go +++ b/pkg/archive/fsBackend.go @@ -6,6 +6,7 @@ package archive import ( "bufio" + "bytes" "encoding/json" "fmt" "os" @@ -14,6 +15,7 @@ import ( "strconv" "time" + "github.com/ClusterCockpit/cc-backend/internal/config" "github.com/ClusterCockpit/cc-backend/pkg/log" "github.com/ClusterCockpit/cc-backend/pkg/schema" ) @@ -100,14 +102,17 @@ func (fsa *FsArchive) LoadJobMeta(job *schema.Job) (*schema.JobMeta, error) { func (fsa *FsArchive) LoadClusterCfg(name string) (*schema.Cluster, error) { - f, err := os.Open(filepath.Join(fsa.path, name, "cluster.json")) + b, err := os.ReadFile(filepath.Join(fsa.path, name, "cluster.json")) if err != nil { log.Errorf("fsBackend LoadClusterCfg()- %v", err) return &schema.Cluster{}, err } - defer f.Close() - - return DecodeCluster(bufio.NewReader(f)) + if config.Keys.Validate { + if err := schema.Validate(schema.ClusterCfg, bytes.NewReader(b)); err != nil { + return &schema.Cluster{}, err + } + } + return DecodeCluster(bytes.NewReader(b)) } func (fsa *FsArchive) Iter() <-chan *schema.JobMeta { diff --git a/pkg/archive/fsBackend_test.go b/pkg/archive/fsBackend_test.go index 962aa23..1b2fb24 100644 --- a/pkg/archive/fsBackend_test.go +++ b/pkg/archive/fsBackend_test.go @@ -11,6 +11,7 @@ import ( "time" "github.com/ClusterCockpit/cc-backend/pkg/schema" + _ "github.com/santhosh-tekuri/jsonschema/v5/httploader" ) func TestInitEmptyPath(t *testing.T) { diff --git a/pkg/schema/config.go b/pkg/schema/config.go index 253ae2d..9aa8697 100644 --- a/pkg/schema/config.go +++ b/pkg/schema/config.go @@ -78,6 +78,9 @@ type ProgramConfig struct { // do not write to the job-archive. DisableArchive bool `json:"disable-archive"` + // Validate json input against schema + Validate bool `json:"validate"` + // For LDAP Authentication and user synchronisation. LdapConfig *LdapConfig `json:"ldap"` JwtConfig *JWTAuthConfig `json:"jwts"` diff --git a/pkg/schema/validate.go b/pkg/schema/validate.go index 949d7e7..7d44e77 100644 --- a/pkg/schema/validate.go +++ b/pkg/schema/validate.go @@ -5,10 +5,12 @@ package schema import ( + "encoding/json" "fmt" "io" - "github.com/santhosh-tekuri/jsonschema" + "github.com/ClusterCockpit/cc-backend/pkg/log" + "github.com/santhosh-tekuri/jsonschema/v5" ) type Kind int @@ -19,7 +21,7 @@ const ( ClusterCfg ) -func Validate(k Kind, v io.Reader) (err error) { +func Validate(k Kind, r io.Reader) (err error) { var s *jsonschema.Schema switch k { @@ -37,9 +39,15 @@ func Validate(k Kind, v io.Reader) (err error) { return err } - if err = s.Validate(v); err != nil { + var v interface{} + if err := json.NewDecoder(r).Decode(&v); err != nil { + log.Error("schema.Validate() - Failed to decode %v", err) return err } + if err = s.Validate(v); err != nil { + return fmt.Errorf("%#v", err) + } + return nil } diff --git a/test/api_test.go b/test/api_test.go index ed1304d..2d839b1 100644 --- a/test/api_test.go +++ b/test/api_test.go @@ -24,6 +24,7 @@ import ( "github.com/gorilla/mux" _ "github.com/mattn/go-sqlite3" + _ "github.com/santhosh-tekuri/jsonschema/v5/httploader" ) func setup(t *testing.T) *api.RestApi {