mirror of
https://github.com/SAP/jenkins-library.git
synced 2024-12-14 11:03:09 +02:00
124 lines
3.5 KiB
Go
124 lines
3.5 KiB
Go
|
package malwarescan
|
||
|
|
||
|
import (
|
||
|
"encoding/json"
|
||
|
"fmt"
|
||
|
piperhttp "github.com/SAP/jenkins-library/pkg/http"
|
||
|
"github.com/pkg/errors"
|
||
|
"io"
|
||
|
"io/ioutil"
|
||
|
"net/http"
|
||
|
)
|
||
|
|
||
|
// ScanResult : Returned by the scan endpoint of the malwarescan api of SAP CP
|
||
|
type ScanResult struct {
|
||
|
MalwareDetected bool `json:"malwareDetected"`
|
||
|
EncryptedContentDetected bool `json:"encryptedContentDetected"`
|
||
|
ScanSize int `json:"scanSize"`
|
||
|
Finding string `json:"finding,omitempty"`
|
||
|
MimeType string `json:"mimeType"`
|
||
|
SHA256 string `json:"SHA256"`
|
||
|
}
|
||
|
|
||
|
// Info : Returned by the info endpoint of the malwarescan api of SAP CP
|
||
|
type Info struct {
|
||
|
MaxScanSize int
|
||
|
SignatureTimestamp string
|
||
|
EngineVersion string
|
||
|
}
|
||
|
|
||
|
// ScanError : Returned by the malwarescan api of SAP CP in case of an error
|
||
|
type ScanError struct {
|
||
|
Message string
|
||
|
}
|
||
|
|
||
|
// Client : Interface for the malwarescan api provided by SAP CP (see https://api.sap.com/api/MalwareScanAPI/overview)
|
||
|
type Client interface {
|
||
|
Scan(candidate io.Reader) (*ScanResult, error)
|
||
|
Info() (*Info, error)
|
||
|
}
|
||
|
|
||
|
// ClientImpl : Client implementation of the malwarescan api provided by SAP CP (see https://api.sap.com/api/MalwareScanAPI/overview)
|
||
|
type ClientImpl struct {
|
||
|
HTTPClient piperhttp.Sender
|
||
|
Host string
|
||
|
}
|
||
|
|
||
|
// Scan : Triggers a malwarescan in SAP CP for the given content.
|
||
|
func (c *ClientImpl) Scan(candidate io.Reader) (*ScanResult, error) {
|
||
|
var scanResult ScanResult
|
||
|
|
||
|
headers := http.Header{}
|
||
|
headers.Add("Content-Type", "application/octet-stream")
|
||
|
|
||
|
err := c.sendAPIRequest("POST", "/scan", candidate, headers, &scanResult)
|
||
|
|
||
|
if err != nil {
|
||
|
return nil, err
|
||
|
}
|
||
|
|
||
|
return &scanResult, nil
|
||
|
|
||
|
}
|
||
|
|
||
|
// Info : Returns some information about the scanengine used by the malwarescan service.
|
||
|
func (c *ClientImpl) Info() (*Info, error) {
|
||
|
var info Info
|
||
|
|
||
|
err := c.sendAPIRequest("GET", "/info", nil, nil, &info)
|
||
|
|
||
|
if err != nil {
|
||
|
return nil, err
|
||
|
}
|
||
|
|
||
|
return &info, nil
|
||
|
}
|
||
|
|
||
|
func (c *ClientImpl) sendAPIRequest(method, endpoint string, body io.Reader, header http.Header, obj interface{}) error {
|
||
|
// piper http utils mashall some http response codes into errors. We wan't to check the status code
|
||
|
// ourselves hence we wait with returning that error (maybe also related to errors others than http status codes)
|
||
|
|
||
|
// sendRequest results in any combination of nil and non-nil response and error.
|
||
|
// a response body could even be already closed.
|
||
|
response, err := c.HTTPClient.SendRequest(method, c.Host+endpoint, body, header, nil)
|
||
|
|
||
|
if response.StatusCode != 200 {
|
||
|
var scanError ScanError
|
||
|
|
||
|
err = c.unmarshalResponse(response, &scanError)
|
||
|
|
||
|
if err != nil {
|
||
|
return fmt.Errorf("MalwareService returned with status code %d, no further information available", response.StatusCode)
|
||
|
}
|
||
|
|
||
|
return fmt.Errorf("MalwareService returned with status code %d: %s", response.StatusCode, scanError.Message)
|
||
|
}
|
||
|
|
||
|
return c.unmarshalResponse(response, obj)
|
||
|
}
|
||
|
|
||
|
func (c *ClientImpl) readBody(response *http.Response) ([]byte, error) {
|
||
|
if response != nil && response.Body != nil {
|
||
|
defer response.Body.Close()
|
||
|
return ioutil.ReadAll(response.Body)
|
||
|
}
|
||
|
|
||
|
return nil, fmt.Errorf("No response body available")
|
||
|
}
|
||
|
|
||
|
func (c *ClientImpl) unmarshalResponse(response *http.Response, obj interface{}) error {
|
||
|
body, err := c.readBody(response)
|
||
|
|
||
|
if err != nil {
|
||
|
return err
|
||
|
}
|
||
|
|
||
|
err = json.Unmarshal(body, obj)
|
||
|
|
||
|
if err != nil {
|
||
|
return errors.Wrap(err, fmt.Sprintf("Unmarshalling of response body failed. Body: '%s'", body))
|
||
|
}
|
||
|
|
||
|
return err
|
||
|
}
|