From ab0ac54a7d935d00c8704772ca118ef94f3e7807 Mon Sep 17 00:00:00 2001 From: Paul Weil Date: Mon, 11 Apr 2016 14:38:42 -0400 Subject: [PATCH 1/2] factor out image serving --- cmd/image-inspector.go | 3 +- pkg/api/types.go | 57 +++++++++++++ pkg/cmd/types.go | 13 +-- pkg/imageserver/types.go | 43 ++++++++++ pkg/imageserver/webdav.go | 114 +++++++++++++++++++++++++ pkg/inspector/image-inspector.go | 118 +++++++------------------- pkg/inspector/image-inspector_test.go | 15 +++- pkg/inspector/types.go | 46 ---------- 8 files changed, 270 insertions(+), 139 deletions(-) create mode 100644 pkg/api/types.go create mode 100644 pkg/imageserver/types.go create mode 100644 pkg/imageserver/webdav.go diff --git a/cmd/image-inspector.go b/cmd/image-inspector.go index 06b8e53..0c9003f 100644 --- a/cmd/image-inspector.go +++ b/cmd/image-inspector.go @@ -5,6 +5,7 @@ import ( "fmt" "log" + iiapi "github.com/openshift/image-inspector/pkg/api" iicmd "github.com/openshift/image-inspector/pkg/cmd" ii "github.com/openshift/image-inspector/pkg/inspector" ) @@ -20,7 +21,7 @@ func main() { flag.Var(&inspectorOptions.DockerCfg, "dockercfg", "Location of the docker configuration files. May be specified more than once") flag.StringVar(&inspectorOptions.Username, "username", inspectorOptions.Username, "username for authenticating with the docker registry") flag.StringVar(&inspectorOptions.PasswordFile, "password-file", inspectorOptions.PasswordFile, "Location of a file that contains the password for authentication with the docker registry") - flag.StringVar(&inspectorOptions.ScanType, "scan-type", inspectorOptions.ScanType, fmt.Sprintf("The type of the scan to be done on the inspected image. Available scan types are: %v", iicmd.ScanOptions)) + flag.StringVar(&inspectorOptions.ScanType, "scan-type", inspectorOptions.ScanType, fmt.Sprintf("The type of the scan to be done on the inspected image. Available scan types are: %v", iiapi.ScanOptions)) flag.StringVar(&inspectorOptions.ScanResultsDir, "scan-results-dir", inspectorOptions.ScanResultsDir, "The directory that will contain the results of the scan") flag.BoolVar(&inspectorOptions.OpenScapHTML, "openscap-html-report", inspectorOptions.OpenScapHTML, "Generate an OpenScap HTML report in addition to the ARF formatted report") flag.StringVar(&inspectorOptions.CVEUrlPath, "cve-url", inspectorOptions.CVEUrlPath, "An alternative URL source for CVE files") diff --git a/pkg/api/types.go b/pkg/api/types.go new file mode 100644 index 0000000..1684698 --- /dev/null +++ b/pkg/api/types.go @@ -0,0 +1,57 @@ +package api + +import ( + docker "github.com/fsouza/go-dockerclient" + "time" +) + +// OpenSCAPStatus is the status of openscap scan +type OpenSCAPStatus string + +const ( + StatusNotRequested OpenSCAPStatus = "NotRequested" + StatusSuccess OpenSCAPStatus = "Success" + StatusError OpenSCAPStatus = "Error" +) + +type openSCAPMetadata struct { + Status OpenSCAPStatus // Status of the OpenSCAP scan report + ErrorMessage string // Error message from the openscap + ContentTimeStamp string // Timestamp for this data +} + +func (osm *openSCAPMetadata) SetError(err error) { + osm.Status = StatusError + osm.ErrorMessage = err.Error() + osm.ContentTimeStamp = string(time.Now().Format(time.RFC850)) +} + +var ( + ScanOptions = []string{"openscap"} +) + +// InspectorMetadata is the metadata type with information about image-inspector's operation +type InspectorMetadata struct { + docker.Image // Metadata about the inspected image + + OpenSCAP *openSCAPMetadata +} + +// NewInspectorMetadata returns a new InspectorMetadata out of *docker.Image +// The OpenSCAP status will be NotRequested +func NewInspectorMetadata(imageMetadata *docker.Image) *InspectorMetadata { + return &InspectorMetadata{ + Image: *imageMetadata, + OpenSCAP: &openSCAPMetadata{ + Status: StatusNotRequested, + ErrorMessage: "", + ContentTimeStamp: string(time.Now().Format(time.RFC850)), + }, + } +} + +// APIVersions holds a slice of supported API versions. +type APIVersions struct { + // Versions is the supported API versions + Versions []string `json:"versions"` +} diff --git a/pkg/cmd/types.go b/pkg/cmd/types.go index 769cfc1..f4b774d 100644 --- a/pkg/cmd/types.go +++ b/pkg/cmd/types.go @@ -2,12 +2,12 @@ package cmd import ( "fmt" + oscapscanner "github.com/openshift/image-inspector/pkg/openscap" - "os" -) -var ( - ScanOptions = []string{"openscap"} + iiapi "github.com/openshift/image-inspector/pkg/api" + + "os" ) // MultiStringVar is implementing flag.Value @@ -110,14 +110,15 @@ func (i *ImageInspectorOptions) Validate() error { } if len(i.ScanType) > 0 { var found bool = false - for _, opt := range ScanOptions { + for _, opt := range iiapi.ScanOptions { if i.ScanType == opt { found = true break } } if !found { - return fmt.Errorf("%s is not one of the available scan-types which are %v", i.ScanType, ScanOptions) + return fmt.Errorf("%s is not one of the available scan-types which are %v", + i.ScanType, iiapi.ScanOptions) } } diff --git a/pkg/imageserver/types.go b/pkg/imageserver/types.go new file mode 100644 index 0000000..093e388 --- /dev/null +++ b/pkg/imageserver/types.go @@ -0,0 +1,43 @@ +package imageserver + +import ( + docker "github.com/fsouza/go-dockerclient" + iiapi "github.com/openshift/image-inspector/pkg/api" +) + +// ImageServer abstracts the serving of image information. +type ImageServer interface { + // ServeImage Serves the image + ServeImage(imageMetadata *docker.Image, + meta *iiapi.InspectorMetadata, + scanReport []byte, + htmlScanReport []byte) error +} + +// ImageServerOptions is used to configure an image server. +type ImageServerOptions struct { + // ServePath is the root path/port of serving. ex 0.0.0.0:8080 + ServePath string + // HealthzURL is the relative url of the health check. ex /healthz + HealthzURL string + // APIURL is the relative url where the api will be served. ex /api + APIURL string + // APIVersions are the supported API versions. + APIVersions iiapi.APIVersions + // MetadataURL is the relative url of the metadata content. ex /api/v1/metadata + MetadataURL string + // ContentURL is the relative url of the content. ex /api/v1/content/ + ContentURL string + // ImageServeURL is the location that the image is being served from. + // NOTE: if the image server supports a chroot the server implementation will perform + // the chroot based on this URL. + ImageServeURL string + // ScanType is the type of the scan that was done on the inspected image + ScanType string + // ScanReportURL is the url to publish the scan report + ScanReportURL string + // HTMLScanReport wether or not to publish an HTML scan report + HTMLScanReport bool + // HTMLScanReportURL url for the scan html report + HTMLScanReportURL string +} diff --git a/pkg/imageserver/webdav.go b/pkg/imageserver/webdav.go new file mode 100644 index 0000000..6f0b9fb --- /dev/null +++ b/pkg/imageserver/webdav.go @@ -0,0 +1,114 @@ +package imageserver + +import ( + "encoding/json" + "fmt" + "log" + "net/http" + "syscall" + + "golang.org/x/net/webdav" + + docker "github.com/fsouza/go-dockerclient" + iiapi "github.com/openshift/image-inspector/pkg/api" +) + +const ( + // CHROOT_SERVE_PATH is the path to server if we are performing a chroot + // this probably does not belong here. + CHROOT_SERVE_PATH = "/" +) + +// webdavImageServer implements ImageServer. +type webdavImageServer struct { + opts ImageServerOptions + chroot bool +} + +// ensures this always implements the interface or fail compilation. +var _ ImageServer = &webdavImageServer{} + +// NewWebdavImageServer creates a new webdav image server. +func NewWebdavImageServer(opts ImageServerOptions, chroot bool) ImageServer { + return &webdavImageServer{ + opts: opts, + chroot: chroot, + } +} + +// ServeImage Serves the image. +func (s *webdavImageServer) ServeImage(imageMetadata *docker.Image, + meta *iiapi.InspectorMetadata, + scanReport []byte, + htmlScanReport []byte) error { + + servePath := s.opts.ImageServeURL + if s.chroot { + if err := syscall.Chroot(s.opts.ImageServeURL); err != nil { + return fmt.Errorf("Unable to chroot into %s: %v\n", s.opts.ImageServeURL, err) + } + servePath = CHROOT_SERVE_PATH + } else { + log.Printf("!!!WARNING!!! It is insecure to serve the image content without changing") + log.Printf("root (--chroot). Absolute-path symlinks in the image can lead to disclose") + log.Printf("information of the hosting system.") + } + + log.Printf("Serving image content %s on webdav://%s%s", s.opts.ImageServeURL, s.opts.ServePath, s.opts.ContentURL) + + http.HandleFunc(s.opts.HealthzURL, func(w http.ResponseWriter, r *http.Request) { + w.Write([]byte("ok\n")) + }) + + http.HandleFunc(s.opts.APIURL, func(w http.ResponseWriter, r *http.Request) { + body, err := json.MarshalIndent(s.opts.APIVersions, "", " ") + if err != nil { + http.Error(w, err.Error(), http.StatusInternalServerError) + return + } + w.Write(body) + }) + + http.HandleFunc(s.opts.MetadataURL, func(w http.ResponseWriter, r *http.Request) { + body, err := json.MarshalIndent(meta, "", " ") + if err != nil { + http.Error(w, err.Error(), http.StatusInternalServerError) + return + } + w.Write(body) + }) + + http.HandleFunc(s.opts.ScanReportURL, func(w http.ResponseWriter, r *http.Request) { + if s.opts.ScanType != "" && meta.OpenSCAP.Status == iiapi.StatusSuccess { + w.Write(scanReport) + } else { + if meta.OpenSCAP.Status == iiapi.StatusError { + http.Error(w, fmt.Sprintf("OpenSCAP Error: %s", meta.OpenSCAP.ErrorMessage), + http.StatusInternalServerError) + } else { + http.Error(w, "OpenSCAP option was not chosen", http.StatusNotFound) + } + } + }) + + http.HandleFunc(s.opts.HTMLScanReportURL, func(w http.ResponseWriter, r *http.Request) { + if s.opts.ScanType != "" && meta.OpenSCAP.Status == iiapi.StatusSuccess && s.opts.HTMLScanReport { + w.Write(htmlScanReport) + } else { + if meta.OpenSCAP.Status == iiapi.StatusError { + http.Error(w, fmt.Sprintf("OpenSCAP Error: %s", meta.OpenSCAP.ErrorMessage), + http.StatusInternalServerError) + } else { + http.Error(w, "OpenSCAP option was not chosen", http.StatusNotFound) + } + } + }) + + http.Handle(s.opts.ContentURL, &webdav.Handler{ + Prefix: s.opts.ContentURL, + FileSystem: webdav.Dir(servePath), + LockSystem: webdav.NewMemLS(), + }) + + return http.ListenAndServe(s.opts.ServePath, nil) +} diff --git a/pkg/inspector/image-inspector.go b/pkg/inspector/image-inspector.go index 3136be8..69c1ead 100644 --- a/pkg/inspector/image-inspector.go +++ b/pkg/inspector/image-inspector.go @@ -1,33 +1,27 @@ package inspector import ( - "encoding/json" "fmt" "io" "io/ioutil" "log" "math" "math/big" - "net/http" "os" "path" "strings" - "syscall" - "time" "archive/tar" "crypto/rand" docker "github.com/fsouza/go-dockerclient" "github.com/openshift/image-inspector/pkg/openscap" - "golang.org/x/net/webdav" iicmd "github.com/openshift/image-inspector/pkg/cmd" -) -type APIVersions struct { - Versions []string `json:"versions"` -} + iiapi "github.com/openshift/image-inspector/pkg/api" + apiserver "github.com/openshift/image-inspector/pkg/imageserver" +) const ( VERSION_TAG = "v1" @@ -56,13 +50,36 @@ type ImageInspector interface { // defaultImageInspector is the default implementation of ImageInspector. type defaultImageInspector struct { opts iicmd.ImageInspectorOptions - meta InspectorMetadata + meta iiapi.InspectorMetadata + // an optional image server that will server content for inspection. + imageServer apiserver.ImageServer } // NewDefaultImageInspector provides a new default inspector. func NewDefaultImageInspector(opts iicmd.ImageInspectorOptions) ImageInspector { - return &defaultImageInspector{opts, - *NewInspectorMetadata(&docker.Image{})} + inspector := &defaultImageInspector{ + opts: opts, + meta: *iiapi.NewInspectorMetadata(&docker.Image{}), + } + + // if serving then set up an image server + if len(opts.Serve) > 0 { + imageServerOpts := apiserver.ImageServerOptions{ + ServePath: opts.Serve, + HealthzURL: HEALTHZ_URL_PATH, + APIURL: API_URL_PREFIX, + APIVersions: iiapi.APIVersions{Versions: []string{VERSION_TAG}}, + MetadataURL: METADATA_URL_PATH, + ContentURL: CONTENT_URL_PREFIX, + ImageServeURL: opts.DstPath, + ScanType: opts.ScanType, + ScanReportURL: OPENSCAP_URL_PATH, + HTMLScanReport: opts.OpenScapHTML, + HTMLScanReportURL: OPENSCAP_REPORT_URL_PATH, + } + inspector.imageServer = apiserver.NewWebdavImageServer(imageServerOpts, opts.Chroot) + } + return inspector } // Inspect inspects and serves the image based on the ImageInspectorOptions. @@ -87,8 +104,6 @@ func (i *defaultImageInspector) Inspect() error { } i.meta.Image = *imageMetadata - supportedVersions := APIVersions{Versions: []string{VERSION_TAG}} - var scanReport []byte var htmlScanReport []byte if i.opts.ScanType == "openscap" { @@ -101,80 +116,13 @@ func (i *defaultImageInspector) Inspect() error { i.meta.OpenSCAP.SetError(err) log.Printf("Unable to scan image: %v", err) } else { - i.meta.OpenSCAP.Status = StatusSuccess + i.meta.OpenSCAP.Status = iiapi.StatusSuccess } } - if len(i.opts.Serve) > 0 { - servePath := i.opts.DstPath - if i.opts.Chroot { - if err := syscall.Chroot(i.opts.DstPath); err != nil { - return fmt.Errorf("Unable to chroot into %s: %v\n", i.opts.DstPath, err) - } - servePath = CHROOT_SERVE_PATH - } else { - log.Printf("!!!WARNING!!! It is insecure to serve the image content without changing") - log.Printf("root (--chroot). Absolute-path symlinks in the image can lead to disclose") - log.Printf("information of the hosting system.") - } - - log.Printf("Serving image content %s on webdav://%s%s", i.opts.DstPath, i.opts.Serve, CONTENT_URL_PREFIX) - - http.HandleFunc(HEALTHZ_URL_PATH, func(w http.ResponseWriter, r *http.Request) { - w.Write([]byte("ok\n")) - }) - - http.HandleFunc(API_URL_PREFIX, func(w http.ResponseWriter, r *http.Request) { - body, err := json.MarshalIndent(supportedVersions, "", " ") - if err != nil { - http.Error(w, err.Error(), http.StatusInternalServerError) - return - } - w.Write(body) - }) - - http.HandleFunc(METADATA_URL_PATH, func(w http.ResponseWriter, r *http.Request) { - body, err := json.MarshalIndent(i.meta, "", " ") - if err != nil { - http.Error(w, err.Error(), http.StatusInternalServerError) - return - } - w.Write(body) - }) - - http.HandleFunc(OPENSCAP_URL_PATH, func(w http.ResponseWriter, r *http.Request) { - if i.opts.ScanType == "openscap" && i.meta.OpenSCAP.Status == StatusSuccess { - w.Write(scanReport) - } else { - if i.meta.OpenSCAP.Status == StatusError { - http.Error(w, fmt.Sprintf("OpenSCAP Error: %s", i.meta.OpenSCAP.ErrorMessage), - http.StatusInternalServerError) - } else { - http.Error(w, "OpenSCAP option was not chosen", http.StatusNotFound) - } - } - }) - - http.HandleFunc(OPENSCAP_REPORT_URL_PATH, func(w http.ResponseWriter, r *http.Request) { - if i.opts.ScanType == "openscap" && i.meta.OpenSCAP.Status == StatusSuccess && i.opts.OpenScapHTML { - w.Write(htmlScanReport) - } else { - if i.meta.OpenSCAP.Status == StatusError { - http.Error(w, fmt.Sprintf("OpenSCAP Error: %s", i.meta.OpenSCAP.ErrorMessage), - http.StatusInternalServerError) - } else { - http.Error(w, "OpenSCAP option was not chosen", http.StatusNotFound) - } - } - }) - - http.Handle(CONTENT_URL_PREFIX, &webdav.Handler{ - Prefix: CONTENT_URL_PREFIX, - FileSystem: webdav.Dir(servePath), - LockSystem: webdav.NewMemLS(), - }) - - return http.ListenAndServe(i.opts.Serve, nil) + if i.imageServer != nil { + return i.imageServer.ServeImage(imageMetadata, &i.meta, + scanReport, htmlScanReport) } return nil } diff --git a/pkg/inspector/image-inspector_test.go b/pkg/inspector/image-inspector_test.go index 4e14974..bae93b0 100644 --- a/pkg/inspector/image-inspector_test.go +++ b/pkg/inspector/image-inspector_test.go @@ -2,6 +2,10 @@ package inspector import ( "fmt" + docker "github.com/fsouza/go-dockerclient" + iiapi "github.com/openshift/image-inspector/pkg/api" + iicmd "github.com/openshift/image-inspector/pkg/cmd" + "github.com/openshift/image-inspector/pkg/openscap" "io/ioutil" "os" "testing" @@ -47,6 +51,15 @@ func (ms *NoResMockScanner) ResultsFileName() string { return "NoSuchFILE" } +type MockImageServer struct{} + +func (mis *MockImageServer) ServeImage(imageMetadata *docker.Image, + meta *iiapi.InspectorMetadata, + scanReport []byte, + htmlScanReport []byte) error { + return nil +} + func TestScanImage(t *testing.T) { iiWithHtml := defaultImageInspector{} iiWithHtml.opts.OpenScapHTML = true @@ -143,7 +156,7 @@ func TestGetAuthConfigs(t *testing.T) { } for k, v := range tests { - ii := &defaultImageInspector{*v.opts, InspectorMetadata{}} + ii := &defaultImageInspector{*v.opts, iiapi.InspectorMetadata{}, &MockImageServer{}} auths, err := ii.getAuthConfigs() if !v.shouldFail { if err != nil { diff --git a/pkg/inspector/types.go b/pkg/inspector/types.go index 2f0535b..6cd19d5 100644 --- a/pkg/inspector/types.go +++ b/pkg/inspector/types.go @@ -1,47 +1 @@ package inspector - -import ( - docker "github.com/fsouza/go-dockerclient" - "time" -) - -// OpenSCAPStatus is the status of openscap scan -type OpenSCAPStatus string - -const ( - StatusNotRequested OpenSCAPStatus = "NotRequested" - StatusSuccess OpenSCAPStatus = "Success" - StatusError OpenSCAPStatus = "Error" -) - -type openSCAPMetadata struct { - Status OpenSCAPStatus // Status of the OpenSCAP scan report - ErrorMessage string // Error message from the openscap - ContentTimeStamp string // Timestamp for this data -} - -func (osm *openSCAPMetadata) SetError(err error) { - osm.Status = StatusError - osm.ErrorMessage = err.Error() - osm.ContentTimeStamp = string(time.Now().Format(time.RFC850)) -} - -// InspectorMetadata is the metadata type with information about image-inspector's operation -type InspectorMetadata struct { - docker.Image // Metadata about the inspected image - - OpenSCAP *openSCAPMetadata -} - -// NewInspectorMetadata returns a new InspectorMetadata out of *docker.Image -// The OpenSCAP status will be NotRequested -func NewInspectorMetadata(imageMetadata *docker.Image) *InspectorMetadata { - return &InspectorMetadata{ - Image: *imageMetadata, - OpenSCAP: &openSCAPMetadata{ - Status: StatusNotRequested, - ErrorMessage: "", - ContentTimeStamp: string(time.Now().Format(time.RFC850)), - }, - } -} From aad87b99f51951faa7bbd1081e62c88c009beae9 Mon Sep 17 00:00:00 2001 From: Erez Freiberger Date: Tue, 27 Sep 2016 16:50:27 +0300 Subject: [PATCH 2/2] serving scan reports and adding tests --- pkg/api/types.go | 21 ++++----------------- pkg/imageserver/types.go | 4 +--- pkg/imageserver/webdav.go | 4 +--- pkg/inspector/image-inspector.go | 19 +++++++++++++++++-- pkg/inspector/image-inspector_test.go | 15 +-------------- 5 files changed, 24 insertions(+), 39 deletions(-) diff --git a/pkg/api/types.go b/pkg/api/types.go index 1684698..638b6c9 100644 --- a/pkg/api/types.go +++ b/pkg/api/types.go @@ -14,13 +14,13 @@ const ( StatusError OpenSCAPStatus = "Error" ) -type openSCAPMetadata struct { +type OpenSCAPMetadata struct { Status OpenSCAPStatus // Status of the OpenSCAP scan report ErrorMessage string // Error message from the openscap ContentTimeStamp string // Timestamp for this data } -func (osm *openSCAPMetadata) SetError(err error) { +func (osm *OpenSCAPMetadata) SetError(err error) { osm.Status = StatusError osm.ErrorMessage = err.Error() osm.ContentTimeStamp = string(time.Now().Format(time.RFC850)) @@ -33,21 +33,8 @@ var ( // InspectorMetadata is the metadata type with information about image-inspector's operation type InspectorMetadata struct { docker.Image // Metadata about the inspected image - - OpenSCAP *openSCAPMetadata -} - -// NewInspectorMetadata returns a new InspectorMetadata out of *docker.Image -// The OpenSCAP status will be NotRequested -func NewInspectorMetadata(imageMetadata *docker.Image) *InspectorMetadata { - return &InspectorMetadata{ - Image: *imageMetadata, - OpenSCAP: &openSCAPMetadata{ - Status: StatusNotRequested, - ErrorMessage: "", - ContentTimeStamp: string(time.Now().Format(time.RFC850)), - }, - } + // OpenSCAP describes the state of the OpenSCAP scan + OpenSCAP *OpenSCAPMetadata } // APIVersions holds a slice of supported API versions. diff --git a/pkg/imageserver/types.go b/pkg/imageserver/types.go index 093e388..6efd8c4 100644 --- a/pkg/imageserver/types.go +++ b/pkg/imageserver/types.go @@ -1,15 +1,13 @@ package imageserver import ( - docker "github.com/fsouza/go-dockerclient" iiapi "github.com/openshift/image-inspector/pkg/api" ) // ImageServer abstracts the serving of image information. type ImageServer interface { // ServeImage Serves the image - ServeImage(imageMetadata *docker.Image, - meta *iiapi.InspectorMetadata, + ServeImage(meta *iiapi.InspectorMetadata, scanReport []byte, htmlScanReport []byte) error } diff --git a/pkg/imageserver/webdav.go b/pkg/imageserver/webdav.go index 6f0b9fb..8b7ef1f 100644 --- a/pkg/imageserver/webdav.go +++ b/pkg/imageserver/webdav.go @@ -9,7 +9,6 @@ import ( "golang.org/x/net/webdav" - docker "github.com/fsouza/go-dockerclient" iiapi "github.com/openshift/image-inspector/pkg/api" ) @@ -37,8 +36,7 @@ func NewWebdavImageServer(opts ImageServerOptions, chroot bool) ImageServer { } // ServeImage Serves the image. -func (s *webdavImageServer) ServeImage(imageMetadata *docker.Image, - meta *iiapi.InspectorMetadata, +func (s *webdavImageServer) ServeImage(meta *iiapi.InspectorMetadata, scanReport []byte, htmlScanReport []byte) error { diff --git a/pkg/inspector/image-inspector.go b/pkg/inspector/image-inspector.go index 69c1ead..34ef3b4 100644 --- a/pkg/inspector/image-inspector.go +++ b/pkg/inspector/image-inspector.go @@ -1,6 +1,7 @@ package inspector import ( + "encoding/json" "fmt" "io" "io/ioutil" @@ -10,6 +11,7 @@ import ( "os" "path" "strings" + "time" "archive/tar" "crypto/rand" @@ -55,11 +57,24 @@ type defaultImageInspector struct { imageServer apiserver.ImageServer } +// NewInspectorMetadata returns a new InspectorMetadata out of *docker.Image +// The OpenSCAP status will be NotRequested +func NewInspectorMetadata(imageMetadata *docker.Image) iiapi.InspectorMetadata { + return iiapi.InspectorMetadata{ + Image: *imageMetadata, + OpenSCAP: &iiapi.OpenSCAPMetadata{ + Status: iiapi.StatusNotRequested, + ErrorMessage: "", + ContentTimeStamp: string(time.Now().Format(time.RFC850)), + }, + } +} + // NewDefaultImageInspector provides a new default inspector. func NewDefaultImageInspector(opts iicmd.ImageInspectorOptions) ImageInspector { inspector := &defaultImageInspector{ opts: opts, - meta: *iiapi.NewInspectorMetadata(&docker.Image{}), + meta: NewInspectorMetadata(&docker.Image{}), } // if serving then set up an image server @@ -121,7 +136,7 @@ func (i *defaultImageInspector) Inspect() error { } if i.imageServer != nil { - return i.imageServer.ServeImage(imageMetadata, &i.meta, + return i.imageServer.ServeImage(&i.meta, scanReport, htmlScanReport) } return nil diff --git a/pkg/inspector/image-inspector_test.go b/pkg/inspector/image-inspector_test.go index bae93b0..5d820f9 100644 --- a/pkg/inspector/image-inspector_test.go +++ b/pkg/inspector/image-inspector_test.go @@ -9,10 +9,6 @@ import ( "io/ioutil" "os" "testing" - - docker "github.com/fsouza/go-dockerclient" - iicmd "github.com/openshift/image-inspector/pkg/cmd" - "github.com/openshift/image-inspector/pkg/openscap" ) type FailMockScanner struct{} @@ -51,15 +47,6 @@ func (ms *NoResMockScanner) ResultsFileName() string { return "NoSuchFILE" } -type MockImageServer struct{} - -func (mis *MockImageServer) ServeImage(imageMetadata *docker.Image, - meta *iiapi.InspectorMetadata, - scanReport []byte, - htmlScanReport []byte) error { - return nil -} - func TestScanImage(t *testing.T) { iiWithHtml := defaultImageInspector{} iiWithHtml.opts.OpenScapHTML = true @@ -156,7 +143,7 @@ func TestGetAuthConfigs(t *testing.T) { } for k, v := range tests { - ii := &defaultImageInspector{*v.opts, iiapi.InspectorMetadata{}, &MockImageServer{}} + ii := &defaultImageInspector{*v.opts, iiapi.InspectorMetadata{}, nil} auths, err := ii.getAuthConfigs() if !v.shouldFail { if err != nil {