Skip to content

Commit

Permalink
fix: image scanning flows (#6213)
Browse files Browse the repository at this point in the history
* resource scan dev

* image scanning

* review comments

* refactoring

* is imageScanned enabled

* review comments resolved

* remove scanevent struct and replace with common lib struct

* oss app details

* scanned check fix

* revert

---------

Co-authored-by: Prakash Kumar <[email protected]>
  • Loading branch information
Shivam-nagar23 and prakash100198 authored Dec 30, 2024
1 parent 4661653 commit c447ad2
Show file tree
Hide file tree
Showing 27 changed files with 717 additions and 106 deletions.
2 changes: 2 additions & 0 deletions Wire.go
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ import (
"github.com/devtron-labs/devtron/api/infraConfig"
"github.com/devtron-labs/devtron/api/k8s"
"github.com/devtron-labs/devtron/api/module"
"github.com/devtron-labs/devtron/api/resourceScan"
"github.com/devtron-labs/devtron/api/restHandler"
"github.com/devtron-labs/devtron/api/restHandler/app/appInfo"
appList2 "github.com/devtron-labs/devtron/api/restHandler/app/appList"
Expand Down Expand Up @@ -211,6 +212,7 @@ func InitializeApp() (*App, error) {
imageTagging.WireSet,
devtronResource.DevtronResourceWireSet,
policyGovernance.PolicyGovernanceWireSet,
resourceScan.ScanningResultWireSet,

// -------wireset end ----------
// -------
Expand Down
133 changes: 133 additions & 0 deletions api/resourceScan/resourceScanRestHandler.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,133 @@
/*
* Copyright (c) 2024. Devtron Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package resourceScan

import (
"fmt"
"github.com/devtron-labs/devtron/api/restHandler/common"
"github.com/devtron-labs/devtron/pkg/auth/authorisation/casbin"
"github.com/devtron-labs/devtron/pkg/auth/user"
"github.com/devtron-labs/devtron/pkg/policyGovernance/security/imageScanning"
"github.com/devtron-labs/devtron/pkg/policyGovernance/security/imageScanning/bean"
"github.com/devtron-labs/devtron/util/rbac"
"go.uber.org/zap"
"gopkg.in/go-playground/validator.v9"
"net/http"
)

type ScanningResultRestHandler interface {
ScanResults(w http.ResponseWriter, r *http.Request)
}

type ScanningResultRestHandlerImpl struct {
logger *zap.SugaredLogger
userService user.UserService
scanService imageScanning.ImageScanService
enforcer casbin.Enforcer
enforcerUtil rbac.EnforcerUtil
validator *validator.Validate
}

func NewScanningResultRestHandlerImpl(
logger *zap.SugaredLogger,
userService user.UserService,
scanService imageScanning.ImageScanService,
enforcer casbin.Enforcer,
enforcerUtil rbac.EnforcerUtil,
validator *validator.Validate,
) *ScanningResultRestHandlerImpl {
return &ScanningResultRestHandlerImpl{
logger: logger,
userService: userService,
scanService: scanService,
enforcer: enforcer,
enforcerUtil: enforcerUtil,
validator: validator,
}
}

func getResourceScanQueryParams(w http.ResponseWriter, r *http.Request) (*bean.ResourceScanQueryParams, error) {
queryParams := &bean.ResourceScanQueryParams{}
var appId, envId, installedAppId, artifactId, installedAppVersionHistoryId int
var err error
appId, err = common.ExtractIntQueryParam(w, r, "appId", 0)
if err != nil {
return queryParams, err
}
queryParams.AppId = appId

installedAppId, err = common.ExtractIntQueryParam(w, r, "installedAppId", 0)
if err != nil {
return queryParams, err
}
queryParams.InstalledAppId = installedAppId

installedAppVersionHistoryId, err = common.ExtractIntQueryParam(w, r, "installedAppVersionHistoryId", 0)
if err != nil {
return queryParams, err
}
queryParams.InstalledAppVersionHistoryId = installedAppVersionHistoryId

envId, err = common.ExtractIntQueryParam(w, r, "envId", 0)
if err != nil {
return queryParams, err
}
queryParams.EnvId = envId

artifactId, err = common.ExtractIntQueryParam(w, r, "artifactId", 0)
if err != nil {
return queryParams, err
}
queryParams.ArtifactId = artifactId
return queryParams, nil
}

func (impl ScanningResultRestHandlerImpl) ScanResults(w http.ResponseWriter, r *http.Request) {
userId, err := impl.userService.GetLoggedInUser(r)
if userId == 0 || err != nil {
common.WriteJsonResp(w, err, "Unauthorized User", http.StatusUnauthorized)
return
}
resourceScanQueryParams, err := getResourceScanQueryParams(w, r)
if err != nil {
return
}
// RBAC
token := r.Header.Get("token")
object := impl.enforcerUtil.GetAppRBACNameByAppId(resourceScanQueryParams.AppId)
if ok := impl.enforcer.Enforce(token, casbin.ResourceApplications, casbin.ActionGet, object); !ok {
common.WriteJsonResp(w, fmt.Errorf("unauthorized user"), "Unauthorized User", http.StatusForbidden)
return
}
if resourceScanQueryParams.EnvId > 0 {
object = impl.enforcerUtil.GetEnvRBACNameByAppId(resourceScanQueryParams.AppId, resourceScanQueryParams.EnvId)
if ok := impl.enforcer.Enforce(token, casbin.ResourceEnvironment, casbin.ActionGet, object); !ok {
common.WriteJsonResp(w, fmt.Errorf("unauthorized user"), "Unauthorized User", http.StatusForbidden)
return
}
}
// RBAC
resp, err := impl.scanService.GetScanResults(resourceScanQueryParams)
if err != nil {
impl.logger.Errorw("service err, GetScanResults", "resourceScanQueryParams", resourceScanQueryParams, "err", err)
common.WriteJsonResp(w, err, nil, http.StatusInternalServerError)
return
}

common.WriteJsonResp(w, nil, resp, http.StatusOK)

}
37 changes: 37 additions & 0 deletions api/resourceScan/resourceScanRouter.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
/*
* Copyright (c) 2024. Devtron Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package resourceScan

import (
"github.com/gorilla/mux"
)

type ScanningResultRouter interface {
InitScanningResultRouter(configRouter *mux.Router)
}

type ScanningResultRouterImpl struct {
ScanningResultRestHandler ScanningResultRestHandler
}

func NewScanningResultRouterImpl(ScanningResultRestHandler ScanningResultRestHandler) *ScanningResultRouterImpl {
return &ScanningResultRouterImpl{ScanningResultRestHandler: ScanningResultRestHandler}
}

func (router *ScanningResultRouterImpl) InitScanningResultRouter(configRouter *mux.Router) {
configRouter.Path("").HandlerFunc(router.ScanningResultRestHandler.ScanResults).Methods("GET")
}
16 changes: 16 additions & 0 deletions api/resourceScan/wire_scan.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
/*
* Copyright (c) 2024. Devtron Inc.
*/

package resourceScan

import (
"github.com/google/wire"
)

var ScanningResultWireSet = wire.NewSet(
NewScanningResultRouterImpl,
wire.Bind(new(ScanningResultRouter), new(*ScanningResultRouterImpl)),
NewScanningResultRestHandlerImpl,
wire.Bind(new(ScanningResultRestHandler), new(*ScanningResultRestHandlerImpl)),
)
8 changes: 8 additions & 0 deletions api/router/router.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ import (
"github.com/devtron-labs/devtron/api/k8s/application"
"github.com/devtron-labs/devtron/api/k8s/capacity"
"github.com/devtron-labs/devtron/api/module"
"github.com/devtron-labs/devtron/api/resourceScan"
"github.com/devtron-labs/devtron/api/restHandler/common"
"github.com/devtron-labs/devtron/api/router/app"
"github.com/devtron-labs/devtron/api/router/app/configDiff"
Expand Down Expand Up @@ -120,6 +121,7 @@ type MuxRouter struct {
argoApplicationRouter argoApplication.ArgoApplicationRouter
fluxApplicationRouter fluxApplication2.FluxApplicationRouter
devtronResourceRouter devtronResource.DevtronResourceRouter
scanningResultRouter resourceScan.ScanningResultRouter
}

func NewMuxRouter(logger *zap.SugaredLogger,
Expand Down Expand Up @@ -153,6 +155,7 @@ func NewMuxRouter(logger *zap.SugaredLogger,
argoApplicationRouter argoApplication.ArgoApplicationRouter,
devtronResourceRouter devtronResource.DevtronResourceRouter,
fluxApplicationRouter fluxApplication2.FluxApplicationRouter,
scanningResultRouter resourceScan.ScanningResultRouter,
) *MuxRouter {
r := &MuxRouter{
Router: mux.NewRouter(),
Expand Down Expand Up @@ -218,6 +221,7 @@ func NewMuxRouter(logger *zap.SugaredLogger,
argoApplicationRouter: argoApplicationRouter,
devtronResourceRouter: devtronResourceRouter,
fluxApplicationRouter: fluxApplicationRouter,
scanningResultRouter: scanningResultRouter,
}
return r
}
Expand Down Expand Up @@ -321,6 +325,9 @@ func (r MuxRouter) Init() {
imageScanRouter := r.Router.PathPrefix("/orchestrator/security/scan").Subrouter()
r.imageScanRouter.InitImageScanRouter(imageScanRouter)

scanResultRouter := r.Router.PathPrefix("/orchestrator/scan-result").Subrouter()
r.scanningResultRouter.InitScanningResultRouter(scanResultRouter)

policyRouter := r.Router.PathPrefix("/orchestrator/security/policy").Subrouter()
r.policyRouter.InitPolicyRouter(policyRouter)

Expand Down Expand Up @@ -429,4 +436,5 @@ func (r MuxRouter) Init() {

fluxApplicationRouter := r.Router.PathPrefix("/orchestrator/flux-application").Subrouter()
r.fluxApplicationRouter.InitFluxApplicationRouter(fluxApplicationRouter)

}
2 changes: 1 addition & 1 deletion cmd/external-app/wire_gen.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -289,7 +289,7 @@ require gopkg.in/evanphx/json-patch.v4 v4.12.0 // indirect
replace (
github.com/argoproj/argo-workflows/v3 v3.5.10 => github.com/devtron-labs/argo-workflows/v3 v3.5.10
github.com/devtron-labs/authenticator => github.com/devtron-labs/devtron-services/authenticator v0.0.0-20241219033445-6c0c7082c583
github.com/devtron-labs/common-lib => github.com/devtron-labs/devtron-services/common-lib v0.0.0-20241219033445-6c0c7082c583
github.com/devtron-labs/common-lib => github.com/devtron-labs/devtron-services/common-lib v0.0.0-20241225093445-23a98e8bb120
github.com/go-check/check => github.com/go-check/check v0.0.0-20180628173108-788fd7840127
github.com/googleapis/gnostic => github.com/googleapis/gnostic v0.5.5
k8s.io/api => k8s.io/api v0.29.7
Expand Down
4 changes: 2 additions & 2 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -794,8 +794,8 @@ github.com/devtron-labs/argo-workflows/v3 v3.5.10 h1:6rxQOesOzDz6SgQCMDQNHaehsKF
github.com/devtron-labs/argo-workflows/v3 v3.5.10/go.mod h1:/vqxcovDPT4zqr4DjR5v7CF8ggpY1l3TSa2CIG3jmjA=
github.com/devtron-labs/devtron-services/authenticator v0.0.0-20241219033445-6c0c7082c583 h1:YN6O8N4+msUbbmWB+QOpq6ha7hCjF/kkds9bsOZ0EWg=
github.com/devtron-labs/devtron-services/authenticator v0.0.0-20241219033445-6c0c7082c583/go.mod h1:vFJ3M7akwAWCtugDXRW+5Q9P+cp0RiH+K/D5FBbb/JA=
github.com/devtron-labs/devtron-services/common-lib v0.0.0-20241219033445-6c0c7082c583 h1:TmL6N8vzg0/Lq65Y7PVqkRpvRKGAwCS/74dIPMiTJtU=
github.com/devtron-labs/devtron-services/common-lib v0.0.0-20241219033445-6c0c7082c583/go.mod h1:NJSMdv+zTUK3p7rML12RZSeAUKHeLaoY3sR/oK0xhwo=
github.com/devtron-labs/devtron-services/common-lib v0.0.0-20241225093445-23a98e8bb120 h1:HiYR58c/pglJSD79oKUQ2wu/K/aV4G4cQwvgJs/nB/4=
github.com/devtron-labs/devtron-services/common-lib v0.0.0-20241225093445-23a98e8bb120/go.mod h1:NJSMdv+zTUK3p7rML12RZSeAUKHeLaoY3sR/oK0xhwo=
github.com/devtron-labs/go-bitbucket v0.9.60-beta h1:VEx1jvDgdtDPS6A1uUFoaEi0l1/oLhbr+90xOwr6sDU=
github.com/devtron-labs/go-bitbucket v0.9.60-beta/go.mod h1:GnuiCesvh8xyHeMCb+twm8lBR/kQzJYSKL28ZfObp1Y=
github.com/devtron-labs/protos v0.0.3-0.20240802105333-92ee9bb85d80 h1:xwbTeijNTf4/j1v+tSfwVqwLVnReas/NqEKeQHvSTys=
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -300,7 +300,7 @@ func (impl *CdWorkflowRepositoryImpl) FindLatestCdWorkflowRunnerByEnvironmentIdA
var wfr CdWorkflowRunner
err := impl.dbConnection.
Model(&wfr).
Column("cd_workflow_runner.*", "CdWorkflow", "CdWorkflow.Pipeline").
Column("cd_workflow_runner.*", "CdWorkflow", "CdWorkflow.Pipeline", "CdWorkflow.CiArtifact").
Where("p.environment_id = ?", environmentId).
Where("p.app_id = ?", appId).
Where("cd_workflow_runner.workflow_type = ?", runnerType).
Expand Down
20 changes: 3 additions & 17 deletions pkg/policyGovernance/security/imageScanning/CvePolicyService.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import (
"bytes"
"encoding/json"
"fmt"
bean2 "github.com/devtron-labs/common-lib/imageScan/bean"
repository1 "github.com/devtron-labs/devtron/internal/sql/repository/app"
"github.com/devtron-labs/devtron/internal/sql/repository/helper"
"github.com/devtron-labs/devtron/pkg/cluster/environment"
Expand Down Expand Up @@ -133,22 +134,7 @@ type VerifyImageResponse struct {
FixedVersion string
}

type ScanEvent struct {
Image string `json:"image"`
ImageDigest string `json:"imageDigest"`
AppId int `json:"appId"`
EnvId int `json:"envId"`
PipelineId int `json:"pipelineId"`
CiArtifactId int `json:"ciArtifactId"`
UserId int `json:"userId"`
AccessKey string `json:"accessKey"`
SecretKey string `json:"secretKey"`
Token string `json:"token"`
AwsRegion string `json:"awsRegion"`
DockerRegistryId string `json:"dockerRegistryId"`
}

func (impl *PolicyServiceImpl) SendEventToClairUtility(event *ScanEvent) error {
func (impl *PolicyServiceImpl) SendEventToClairUtility(event *bean2.ImageScanEvent) error {
reqBody, err := json.Marshal(event)
if err != nil {
return err
Expand Down Expand Up @@ -228,7 +214,7 @@ func (impl *PolicyServiceImpl) VerifyImage(verifyImageRequest *VerifyImageReques
return nil, err
}
if scanHistory != nil && scanHistory.Id == 0 && objectType != repository3.ScanObjectType_APP {
scanEvent := &ScanEvent{Image: image, ImageDigest: "", PipelineId: 0, UserId: 1}
scanEvent := &bean2.ImageScanEvent{Image: image, ImageDigest: "", PipelineId: 0, UserId: 1}
dockerReg, err := impl.ciTemplateRepository.FindByAppId(app.Id)
if err != nil {
impl.logger.Errorw("error in fetching docker reg ", "err", err)
Expand Down
Loading

0 comments on commit c447ad2

Please sign in to comment.