Skip to content

Commit

Permalink
Merge branch 'main' into ui-changes
Browse files Browse the repository at this point in the history
  • Loading branch information
mohamadch91 committed Dec 16, 2024
2 parents 1396c09 + e511771 commit 4f00fbd
Show file tree
Hide file tree
Showing 9 changed files with 227 additions and 169 deletions.
4 changes: 3 additions & 1 deletion services/describe/api/jobs.go
Original file line number Diff line number Diff line change
Expand Up @@ -136,11 +136,12 @@ type GetComplianceJobsHistoryResponse struct {

type BenchmarkAuditHistoryItem struct {
JobId uint `json:"job_id"`
WithIncidents bool `json:"with_incidents"`
BenchmarkId string `json:"benchmark_id"`
JobStatus ComplianceJobStatus `json:"job_status"`
CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"updated_at"`
IntegrationInfo IntegrationInfo `json:"integration_info"`
IntegrationInfo []IntegrationInfo `json:"integration_info"`
NumberOfIntegrations int `json:"number_of_integrations"`
}

Expand Down Expand Up @@ -264,6 +265,7 @@ type ListComplianceJobsRequest struct {
type BenchmarkAuditHistoryRequest struct {
IntegrationInfo []IntegrationInfoFilter `json:"integration_info"`
JobStatus []string `json:"job_status"`
WithIncidents *bool `json:"with_incidents"`
Interval *string `json:"interval"`
StartTime time.Time `json:"start_time"`
EndTime *time.Time `json:"end_time"`
Expand Down
32 changes: 32 additions & 0 deletions services/describe/db/compliance_quick_run.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,10 @@ package db

import (
"errors"
"github.com/lib/pq"
"github.com/opengovern/opencomply/services/describe/db/model"
"gorm.io/gorm"
"time"
)

func (db Database) CreateComplianceQuickRun(job *model.ComplianceQuickRun) (uint, error) {
Expand Down Expand Up @@ -38,6 +40,36 @@ func (db Database) ListComplianceQuickRuns() ([]model.ComplianceQuickRun, error)
return job, nil
}

func (db Database) ListComplianceQuickRunsByFilters(integrationId []string, benchmarkId []string, status []string,
startTime, endTime *time.Time) ([]model.ComplianceQuickRun, error) {
var jobs []model.ComplianceQuickRun
tx := db.ORM.Model(&model.ComplianceQuickRun{})

if len(integrationId) > 0 {
tx = tx.Where("integration_ids && ?", pq.Array(integrationId))
}

if len(benchmarkId) > 0 {
tx = tx.Where("framework_id IN ?", benchmarkId)
}
if len(status) > 0 {
tx = tx.Where("status IN ?", status)
}
if startTime != nil {
tx = tx.Where("updated_at >= ?", *startTime)
}
if endTime != nil {
tx = tx.Where("updated_at <= ?", *endTime)
}

tx = tx.Find(&jobs)
if tx.Error != nil {
return nil, tx.Error
}

return jobs, nil
}

func (db Database) CleanupAllComplianceQuickRuns() error {
tx := db.ORM.Where("1 = 1").Unscoped().Delete(&model.ComplianceQuickRun{})
if tx.Error != nil {
Expand Down
93 changes: 70 additions & 23 deletions services/describe/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -1198,6 +1198,19 @@ func (h HttpServer) RunBenchmarkById(ctx echo.Context) error {
return echo.NewHTTPError(http.StatusBadRequest, "invalid request")
}

benchmark, err := h.Scheduler.complianceClient.GetBenchmark(&httpclient.Context{UserRole: apiAuth.AdminRole}, benchmarkID)
if err != nil {
return fmt.Errorf("error while getting benchmarks: %v", err)
}
if benchmark == nil {
return echo.NewHTTPError(http.StatusNotFound, "benchmark not found")
}

validIntegrationTypes := make(map[string]bool)
for _, it := range benchmark.IntegrationTypes {
validIntegrationTypes[it] = true
}

var integrations []integrationapi.Integration
for _, info := range request.IntegrationInfo {
if info.IntegrationID != nil {
Expand Down Expand Up @@ -1231,6 +1244,9 @@ func (h HttpServer) RunBenchmarkById(ctx echo.Context) error {
var connectionInfo []api.IntegrationInfo
var connectionIDs []string
for _, c := range integrations {
if _, ok := validIntegrationTypes[c.IntegrationType.String()]; !ok {
return echo.NewHTTPError(http.StatusBadRequest, "invalid integration type for this framework")
}
connectionInfo = append(connectionInfo, api.IntegrationInfo{
IntegrationID: c.IntegrationID,
IntegrationType: string(c.IntegrationType),
Expand All @@ -1240,11 +1256,6 @@ func (h HttpServer) RunBenchmarkById(ctx echo.Context) error {
connectionIDs = append(connectionIDs, c.IntegrationID)
}

benchmark, err := h.Scheduler.complianceClient.GetBenchmark(&httpclient.Context{UserRole: apiAuth.AdminRole}, benchmarkID)
if err != nil {
return fmt.Errorf("error while getting benchmarks: %v", err)
}

if benchmark == nil {
return echo.NewHTTPError(http.StatusNotFound, "benchmark not found")
}
Expand Down Expand Up @@ -2004,30 +2015,64 @@ func (h HttpServer) BenchmarkAuditHistory(ctx echo.Context) error {
startTime = &request.StartTime
endTime = request.EndTime
}

jobs, err := h.DB.ListComplianceJobsByFilters(connectionIDs, []string{benchmarkID}, request.JobStatus, startTime, endTime)
if err != nil {
return echo.NewHTTPError(http.StatusInternalServerError, err.Error())
}

var items []api.BenchmarkAuditHistoryItem
for _, j := range jobs {
item := api.BenchmarkAuditHistoryItem{
JobId: j.ID,
BenchmarkId: j.BenchmarkID,
JobStatus: j.Status.ToApi(),
CreatedAt: j.CreatedAt,
UpdatedAt: j.UpdatedAt,

if request.WithIncidents == nil || *request.WithIncidents == true {
// With Incidents
jobs, err := h.DB.ListComplianceJobsByFilters(connectionIDs, []string{benchmarkID}, request.JobStatus, startTime, endTime)
if err != nil {
h.Scheduler.logger.Error("failed to get list of compliance jobs", zap.Error(err))
return echo.NewHTTPError(http.StatusInternalServerError, "failed to get list of compliance jobs")
}
if info, ok := connectionInfo[j.IntegrationID]; ok {
item.IntegrationInfo = info
item.NumberOfIntegrations = 1

for _, j := range jobs {
item := api.BenchmarkAuditHistoryItem{
JobId: j.ID,
WithIncidents: true,
BenchmarkId: j.BenchmarkID,
JobStatus: j.Status.ToApi(),
CreatedAt: j.CreatedAt,
UpdatedAt: j.UpdatedAt,
}
if info, ok := connectionInfo[j.IntegrationID]; ok {
item.IntegrationInfo = []api.IntegrationInfo{info}
item.NumberOfIntegrations = 1
}

items = append(items, item)
}
}

if request.WithIncidents == nil || *request.WithIncidents == false {
// Without Incidents
jobs2, err := h.DB.ListComplianceQuickRunsByFilters(connectionIDs, []string{benchmarkID}, request.JobStatus, startTime, endTime)
if err != nil {
h.Scheduler.logger.Error("failed to get list of compliance jobs", zap.Error(err))
return echo.NewHTTPError(http.StatusInternalServerError, "failed to get list of compliance jobs")
}

var items2 []api.BenchmarkAuditHistoryItem
for _, j := range jobs2 {
item := api.BenchmarkAuditHistoryItem{
JobId: j.ID,
WithIncidents: false,
BenchmarkId: j.FrameworkID,
JobStatus: api.ComplianceJobStatus(j.Status),
CreatedAt: j.CreatedAt,
UpdatedAt: j.UpdatedAt,
}
item.NumberOfIntegrations = len(j.IntegrationIDs)
for _, i := range j.IntegrationIDs {
if info, ok := connectionInfo[i]; ok {
item.IntegrationInfo = append(item.IntegrationInfo, info)
}
}

items = append(items, item)
items2 = append(items2, item)
}
items = append(items, items2...)
}

totalCount := len(items)
if request.SortBy != nil {
switch strings.ToLower(*request.SortBy) {
case "id":
Expand Down Expand Up @@ -2060,6 +2105,8 @@ func (h HttpServer) BenchmarkAuditHistory(ctx echo.Context) error {
return items[i].UpdatedAt.After(items[j].UpdatedAt)
})
}

totalCount := len(items)
if request.PerPage != nil {
if request.Cursor == nil {
items = utils.Paginate(1, *request.PerPage, items)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
package configs

type IntegrationCredentials struct {
Token string `json:"token"`
Token string `json:"token"`
}
Original file line number Diff line number Diff line change
@@ -1,23 +1,37 @@
package configs

var TablesToResourceTypes = map[string]string{

"doppler_config": "Doppler/Config",
"doppler_environment": "Doppler/Environment",
"doppler_group": "Doppler/Group",
"doppler_integration": "Doppler/Integration",
"doppler_project_member": "Doppler/Project/Member",
"doppler_project_role": "Doppler/Project/Role",
"doppler_project": "Doppler/Project",
"doppler_secret": "Doppler/Secret",
"doppler_service_account": "Doppler/ServiceAccount",
"doppler_service_account_token": "Doppler/ServiceAccount/Token",
"doppler_service_token": "Doppler/ServiceToken",
"doppler_trust_ip": "Doppler/TrustIP",
"doppler_workplace": "Doppler/WorkPlace",
"doppler_workplace_role": "Doppler/WorkPlace/Role",
"doppler_workplace_user": "Doppler/WorkPlace/User",
}

var ResourceTypesList = []string{
"Doppler/Config",
"Doppler/Environment",
"Doppler/Group",
"Doppler/Integration",
"Doppler/Project/Member",
"Doppler/Project/Role",
"Doppler/Project",
"Doppler/Secret",
"Doppler/ServiceAccount",
"Doppler/ServiceAccount/Token",
"Doppler/ServiceToken",
"Doppler/TrustIP",
"Doppler/WorkPlace",
"Doppler/WorkPlace/Role",
"Doppler/WorkPlace/User",
}
"Doppler/Config",
"Doppler/Environment",
"Doppler/Group",
"Doppler/Integration",
"Doppler/Project/Member",
"Doppler/Project/Role",
"Doppler/Project",
"Doppler/Secret",
"Doppler/ServiceAccount",
"Doppler/ServiceAccount/Token",
"Doppler/ServiceToken",
"Doppler/TrustIP",
"Doppler/WorkPlace",
"Doppler/WorkPlace/Role",
"Doppler/WorkPlace/User",
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,85 +4,59 @@ import (
"encoding/json"
"errors"
"fmt"
"io/ioutil"
"net/http"
"time"

)

type ConnectorResponse struct {
Connectors []Connector `json:"connectors"`
TotalCount float64 `json:"total_count"`
// Config represents the JSON input configuration
type Config struct {
Token string `json:"token"`
}




type Connector struct {
ID string `json:"id"`
Name string `json:"name"`
CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"updated_at"`
OrganizationID string `json:"organization_id"`
Description string `json:"description"`
URL string `json:"url"`
Excludes []string `json:"excludes"`
AuthType string `json:"auth_type"`
Oauth Oauth `json:"oauth"`
AuthStatus string `json:"auth_status"`
Active bool `json:"active"`
ContinueOnFailure bool `json:"continue_on_failure"`
// Workplace defines the information for doppler workplace.
type Workplace struct {
ID string `json:"id"`
Name string `json:"name"`
BillingEmail string `json:"billing_email"`
SecurityEmail string `json:"security_email"`
}

type Oauth struct {
AuthorizeURL string `json:"authorize_url"`
TokenURL string `json:"token_url"`
type Response struct {
Workplace Workplace `json:"workplace"`
}

// Discover retrieves Render customer info
func Discover(token string) (*Workplace, error) {
var response Response

url := "https://api.doppler.com/v3/workplace"

func DopplerIntegrationDiscovery(apiKey string) ([]Connector, error) {
if apiKey == "" {
return nil, errors.New("API key is required")
}

// Endpoint to test access
url := "https://api.cohere.com/v1/connectors"
client := http.DefaultClient

// Create HTTP request
req, err := http.NewRequest("GET", url, nil)
if err != nil {
return nil, fmt.Errorf("error creating request: %v", err)
return nil, err
}
req.Header.Set("Content-Type", "application/json")
req.Header.Set("Authorization", fmt.Sprintf("Bearer %s", token))

// Add Authorization header
req.Header.Add("Authorization", "Bearer "+apiKey)

// Execute the request
client := &http.Client{}
resp, err := client.Do(req)
if err != nil {
return nil, fmt.Errorf("error making request: %v", err)
return nil, fmt.Errorf("request execution failed: %w", err)
}
defer resp.Body.Close()

// Check for non-200 status codes
if resp.StatusCode != http.StatusOK {
body, _ := ioutil.ReadAll(resp.Body)
return nil, fmt.Errorf("API error: %s, status code: %d", string(body), resp.StatusCode)
if err = json.NewDecoder(resp.Body).Decode(&response); err != nil {
return nil, fmt.Errorf("failed to decode response: %w", err)
}

// Parse the response to ensure it contains models data
var modelsResponse ConnectorResponse
err = json.NewDecoder(resp.Body).Decode(&modelsResponse)
if err != nil {
return nil, fmt.Errorf("error parsing response: %v", err)
}
return &response.Workplace, nil
}

// Validate that the token provides access to at least one model
if len(modelsResponse.Connectors) == 0 {
return nil, nil // Token valid but no accessible models
func DopplerIntegrationDiscovery(cfg Config) (*Workplace, error) {
// Check for the token
if cfg.Token == "" {
return nil, errors.New("token must be configured")
}

return modelsResponse.Connectors, nil // Token valid and has access
return Discover(cfg.Token)
}
Loading

0 comments on commit 4f00fbd

Please sign in to comment.