diff --git a/apptrust/auth/apptrustdetails.go b/apptrust/auth/apptrustdetails.go new file mode 100644 index 000000000..3dde14ba3 --- /dev/null +++ b/apptrust/auth/apptrustdetails.go @@ -0,0 +1,44 @@ +package auth + +import ( + "github.com/jfrog/jfrog-client-go/apptrust" + "github.com/jfrog/jfrog-client-go/auth" + "github.com/jfrog/jfrog-client-go/config" + "github.com/jfrog/jfrog-client-go/utils/log" +) + +func NewXscDetails() *ApptrustDetails { + return &ApptrustDetails{} +} + +type ApptrustDetails struct { + auth.CommonConfigFields +} + +func (ds *ApptrustDetails) GetVersion() (string, error) { + var err error + if ds.Version == "" { + ds.Version, err = ds.getApptrustVersion() + if err != nil { + return "", err + } + log.Debug("JFrog AppTrust version is:", ds.Version) + } + return ds.Version, nil +} + +func (ds *ApptrustDetails) getApptrustVersion() (string, error) { + cd := auth.ServiceDetails(ds) + serviceConfig, err := config.NewConfigBuilder(). + SetServiceDetails(cd). + SetCertificatesPath(cd.GetClientCertPath()). + Build() + if err != nil { + return "", err + } + sm, err := apptrust.New(serviceConfig) + if err != nil { + return "", err + } + return sm.GetVersion() +} diff --git a/apptrust/manager.go b/apptrust/manager.go new file mode 100644 index 000000000..3d7b9f100 --- /dev/null +++ b/apptrust/manager.go @@ -0,0 +1,58 @@ +package apptrust + +import ( + "github.com/jfrog/jfrog-client-go/apptrust/services" + "github.com/jfrog/jfrog-client-go/config" + "github.com/jfrog/jfrog-client-go/http/jfroghttpclient" +) + +type ApptrustServicesManager struct { + client *jfroghttpclient.JfrogHttpClient + config config.Config +} + +func New(config config.Config) (*ApptrustServicesManager, error) { + details := config.GetServiceDetails() + var err error + manager := &ApptrustServicesManager{config: config} + manager.client, err = jfroghttpclient.JfrogClientBuilder(). + SetCertificatesPath(config.GetCertificatesPath()). + SetInsecureTls(config.IsInsecureTls()). + SetContext(config.GetContext()). + SetDialTimeout(config.GetDialTimeout()). + SetOverallRequestTimeout(config.GetOverallRequestTimeout()). + SetClientCertPath(details.GetClientCertPath()). + SetClientCertKeyPath(details.GetClientCertKeyPath()). + AppendPreRequestInterceptor(details.RunPreRequestFunctions). + SetRetries(config.GetHttpRetries()). + SetRetryWaitMilliSecs(config.GetHttpRetryWaitMilliSecs()). + Build() + return manager, err +} + +func (sm *ApptrustServicesManager) Client() *jfroghttpclient.JfrogHttpClient { + return sm.client +} + +func (sm *ApptrustServicesManager) Config() config.Config { + return sm.config +} + +// Returns AppTrust server version +func (sm *ApptrustServicesManager) GetVersion() (string, error) { + // TODO eran complete this service + return "1.0.0", nil + /* + versionService := services.NewVersionService(sm.client) + versionService.XrayDetails = sm.config.GetServiceDetails() + return versionService.GetVersion() + + */ +} + +// Returns evaluation response from Unified Policy server indicating on evaluation result OR missing scans that are required for performing the evaluation. +func (sm *ApptrustServicesManager) Evaluate(params services.EvaluateRequest) (response services.EvaluateResponse, err error) { + evaluationService := services.NewEvaluationService(sm.client) + evaluationService.ApptrustDetails = sm.config.GetServiceDetails() + return evaluationService.Evaluate(params) +} diff --git a/apptrust/services/evaluate.go b/apptrust/services/evaluate.go new file mode 100644 index 000000000..9472010f9 --- /dev/null +++ b/apptrust/services/evaluate.go @@ -0,0 +1,80 @@ +package services + +import ( + "encoding/json" + "fmt" + "github.com/jfrog/jfrog-client-go/auth" + "github.com/jfrog/jfrog-client-go/http/jfroghttpclient" + "github.com/jfrog/jfrog-client-go/utils" + "github.com/jfrog/jfrog-client-go/utils/errorutils" + "net/http" +) + +const ( + apptrustDomain = "unifiedpolicy/" + evaluateEndpoint = "evaluate" + evaluateApi = apptrustDomain + "api/v1/" + evaluateEndpoint +) + +type EvaluationService struct { + client *jfroghttpclient.JfrogHttpClient + ApptrustDetails auth.ServiceDetails +} + +func NewEvaluationService(client *jfroghttpclient.JfrogHttpClient) *EvaluationService { + return &EvaluationService{client: client} +} + +type EvaluateRequest struct { + Action string `json:"action"` + Context EvaluateContext `json:"context"` + Resource EvaluateResource `json:"resource"` +} + +type EvaluateContext struct { + Stage string `json:"stage"` +} + +type EvaluateResource struct { + ApplicationKey string `json:"application_key"` + Type string `json:"type"` + MultiScanId string `json:"multi_scan_id"` + GitRepoUrl string `json:"git_repo_url"` +} + +type EvaluateResponse struct { + Id string `json:"id"` + Decision string `json:"decision"` + Explanation string `json:"explanation"` + MissingData []string `json:"missing_data"` +} + +func (es *EvaluationService) Evaluate(params EvaluateRequest) (EvaluateResponse, error) { + // TODO eran delete this section - this is a temporary solution that returns the expected response for testing and development until API is implemented + return EvaluateResponse{ + Id: "mock-evaluate-id", + Decision: "Error", + Explanation: "", + MissingData: []string{"sast", "secrets"}, + }, nil + // TODO eran delete up to here + + httpDetail := es.ApptrustDetails.CreateHttpClientDetails() + url := utils.AddTrailingSlashIfNeeded(es.ApptrustDetails.GetUrl()) + evaluateApi + requestBody, err := json.Marshal(params) + if err != nil { + return EvaluateResponse{}, fmt.Errorf("failed to marshal request body: %w", err) + } + + resp, body, err := es.client.SendPost(url, requestBody, &httpDetail) + if err != nil { + return EvaluateResponse{}, fmt.Errorf("failed to send POST request to '%s': %w", url, err) + } + if err = errorutils.CheckResponseStatusWithBody(resp, body, http.StatusOK); err != nil { + return EvaluateResponse{}, err + } + + var response EvaluateResponse + err = errorutils.CheckError(json.Unmarshal(body, &response)) + return response, err +}