Skip to content

Commit 668d369

Browse files
authored
Merge pull request #982 from devtron-labs/trivy-image-scanning
feat: trivy Image scanning module Integration
2 parents 1ab376c + 4d85725 commit 668d369

28 files changed

+821
-111
lines changed

.env

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,4 +29,5 @@ CLUSTER_TERMINAL_CONNECTION_RETRY_COUNT=7
2929
ENABLE_CHART_SEARCH_IN_HELM_DEPLOY=false
3030
HIDE_EXCLUDE_INCLUDE_GIT_COMMITS=true
3131
ENABLE_BUILD_CONTEXT=false
32-
ENABLE_RESTART_WORKLOAD=false
32+
CLAIR_TOOL_VERSION=
33+
ENABLE_RESTART_WORKLOAD=false

src/assets/icons/ic-clair-to-trivy.svg

Lines changed: 20 additions & 0 deletions
Loading

src/assets/icons/ic-clair.svg

Lines changed: 5 additions & 0 deletions
Loading

src/assets/icons/ic-trivy-to-clair.svg

Lines changed: 22 additions & 0 deletions
Loading

src/assets/icons/ic-trivy.svg

Lines changed: 9 additions & 0 deletions
Loading

src/components/app/details/cIDetails/CIDetails.tsx

Lines changed: 26 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ import { useRouteMatch, useParams, useHistory, generatePath } from 'react-router
88
import { BuildDetails, CIPipeline, HistoryLogsType, SecurityTabType } from './types'
99
import { ReactComponent as Down } from '../../../../assets/icons/ic-dropdown-filled.svg'
1010
import { getLastExecutionByArtifactId } from '../../../../services/service'
11-
import { ScanDisabledView, ImageNotScannedView, NoVulnerabilityView, CIRunningView } from './cIDetails.util'
11+
import { ScanDisabledView, ImageNotScannedView, CIRunningView } from './cIDetails.util'
1212
import './ciDetails.scss'
1313
import { getModuleInfo } from '../../../v2/devtronStackManager/DevtronStackManager.service'
1414
import { ModuleStatus } from '../../../v2/devtronStackManager/DevtronStackManager.type'
@@ -20,6 +20,8 @@ import Artifacts from '../cicdHistory/Artifacts'
2020
import { CICDSidebarFilterOptionType, History, HistoryComponentType } from '../cicdHistory/types'
2121
import LogsRenderer from '../cicdHistory/LogsRenderer'
2222
import { EMPTY_STATE_STATUS } from '../../../../config/constantMessaging'
23+
import novulnerability from '../../../../assets/img/ic-vulnerability-not-found.svg';
24+
import { ScannedByToolModal } from '../../../common/security/ScannedByToolModal'
2325

2426
const terminalStatus = new Set(['succeeded', 'failed', 'error', 'cancelled', 'nottriggered', 'notbuilt'])
2527
let statusSet = new Set(['starting', 'running', 'pending'])
@@ -390,6 +392,21 @@ const HistoryLogs = ({ triggerDetails, isBlobStorageConfigured, isJobView, appId
390392
</div>
391393
)
392394
}
395+
export function NoVulnerabilityViewWithTool({scanToolId}:{scanToolId:number}) {
396+
return (
397+
<div className="flex h-100">
398+
<GenericEmptyState
399+
image={novulnerability}
400+
title={EMPTY_STATE_STATUS.CI_DEATILS_NO_VULNERABILITY_FOUND}
401+
children={
402+
<span className="flex workflow__header dc__border-radius-24 bcn-0">
403+
<ScannedByToolModal scanToolId={scanToolId} />
404+
</span>
405+
}
406+
/>
407+
</div>
408+
)
409+
}
393410

394411
const SecurityTab = ({ ciPipelineId, artifactId, status, appIdFromParent }: SecurityTabType) => {
395412
const [isCollapsed, setIsCollapsed] = useState(false)
@@ -405,6 +422,7 @@ const SecurityTab = ({ ciPipelineId, artifactId, status, appIdFromParent }: Secu
405422
scanned: false,
406423
isLoading: !!artifactId,
407424
isError: false,
425+
ScanToolId: null,
408426
})
409427
const { appId } = useParams<{ appId: string }>()
410428
const { push } = useHistory()
@@ -419,6 +437,7 @@ const SecurityTab = ({ ciPipelineId, artifactId, status, appIdFromParent }: Secu
419437
scanned: result.scanned,
420438
isLoading: false,
421439
isError: false,
440+
ScanToolId: result.scanToolId,
422441
})
423442
} catch (error) {
424443
// showError(error);
@@ -433,7 +452,7 @@ const SecurityTab = ({ ciPipelineId, artifactId, status, appIdFromParent }: Secu
433452
function toggleCollapse() {
434453
setIsCollapsed(!isCollapsed)
435454
}
436-
455+
437456
useEffect(() => {
438457
if (artifactId) {
439458
callGetSecurityIssues()
@@ -472,8 +491,9 @@ const SecurityTab = ({ ciPipelineId, artifactId, status, appIdFromParent }: Secu
472491
return <ImageNotScannedView />
473492
}
474493
} else if (artifactId && securityData.scanned && !securityData.vulnerabilities.length) {
475-
return <NoVulnerabilityView />
494+
return <NoVulnerabilityViewWithTool scanToolId={securityData.ScanToolId}/>
476495
}
496+
const scanToolId= securityData.ScanToolId
477497

478498
return (
479499
<>
@@ -497,7 +517,9 @@ const SecurityTab = ({ ciPipelineId, artifactId, status, appIdFromParent }: Secu
497517
{severityCount.critical === 0 && severityCount.moderate === 0 && severityCount.low !== 0 ? (
498518
<span className="dc__fill-low">{severityCount.low} Low</span>
499519
) : null}
500-
<div className="security-scan__type">post build execution</div>
520+
<div className="security-scan__type flex">
521+
<ScannedByToolModal scanToolId={scanToolId}/>
522+
</div>
501523
</div>
502524
{isCollapsed ? (
503525
''

src/components/app/details/cicdHistory/Artifacts.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ import { DOCUMENTATION, TERMINAL_STATUS_MAP } from '../../../../config'
1717
import { extractImage } from '../../service'
1818
import { EMPTY_STATE_STATUS } from '../../../../config/constantMessaging'
1919

20-
const ApprovedArtifact = importComponentFromFELibrary('ApprovedArtifact')
20+
const ApprovedArtifact = importComponentFromFELibrary && importComponentFromFELibrary('ApprovedArtifact')
2121

2222
export default function Artifacts({
2323
status,

src/components/app/details/triggerView/Constants.ts

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,8 @@ export const CI_MATERIAL_EMPTY_STATE_MESSAGING = {
1010
Retry: 'Retry',
1111
WebhookModalCTA: 'View all incoming webhook payloads',
1212
NoCommitEligibleCommit: 'No eligible commit found in recent commits',
13-
NoCommitEligibleCommitSubtitle: 'Commits that contain changes only in excluded files or folders are not eligible for build.',
13+
NoCommitEligibleCommitSubtitle:
14+
'Commits that contain changes only in excluded files or folders are not eligible for build.',
1415
NoCommitEligibleCommitButtonText: 'Show excluded commits',
1516
}
1617
export const IGNORE_CACHE_INFO = {
@@ -25,11 +26,11 @@ export const IGNORE_CACHE_INFO = {
2526
},
2627
CacheNotAvailable: {
2728
title: 'Cache will be generated for this pipeline run',
28-
infoText: 'Cache will be used in future runs to reduce build time.'
29+
infoText: 'Cache will be used in future runs to reduce build time.',
2930
},
3031
IgnoreCache: {
3132
title: 'Ignore Cache',
32-
infoText: 'Ignoring cache will lead to longer build time.'
33+
infoText: 'Ignoring cache will lead to longer build time.',
3334
},
3435
}
3536
export const BRANCH_REGEX_MODAL_MESSAGING = {
@@ -75,11 +76,20 @@ export const TRIGGER_VIEW_GA_EVENTS = {
7576
ApprovalNodeClicked: {
7677
category: 'Trigger View',
7778
action: 'Approval Node Clicked',
78-
}
79+
},
7980
}
8081

8182
export const ARTIFACT_STATUS = {
8283
Progressing: 'Progressing',
8384
Degraded: 'Degraded',
8485
Failed: 'Failed',
8586
}
87+
88+
export const NO_VULNERABILITY_TEXT = {
89+
Secured: 'You’re secure!',
90+
NoVulnerabilityFound: 'No security vulnerability found for this image.',
91+
}
92+
export const IMAGE_SCAN_TOOL = {
93+
Clair: 'Clair',
94+
Trivy: 'Trivy',
95+
}

src/components/app/details/triggerView/TriggerView.tsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -950,6 +950,7 @@ class TriggerView extends Component<TriggerViewProps, TriggerViewState> {
950950
node[this.state.materialType][materialIndex]['lastExecution'] =
951951
response.result.lastExecution
952952
node[this.state.materialType][materialIndex]['vulnerabilitiesLoading'] = false
953+
node[this.state.materialType][materialIndex]['scanToolId']=response.result.scanToolId
953954
}
954955
return node
955956
})

src/components/app/details/triggerView/cdMaterial.tsx

Lines changed: 15 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,6 @@ import { CDButtonLabelMap, getCommonConfigSelectStyles, TriggerViewContext } fro
4242
import { getLatestDeploymentConfig, getRecentDeploymentConfig, getSpecificDeploymentConfig } from '../../service'
4343
import GitCommitInfoGeneric from '../../../common/GitCommitInfoGeneric'
4444
import { getModuleInfo } from '../../../v2/devtronStackManager/DevtronStackManager.service'
45-
import { ModuleNameMap } from '../../../../config'
4645
import { ModuleStatus } from '../../../v2/devtronStackManager/DevtronStackManager.type'
4746
import { DropdownIndicator, Option } from '../../../v2/common/ReactSelect.utils'
4847
import {
@@ -54,7 +53,9 @@ import {
5453
} from './TriggerView.utils'
5554
import TriggerViewConfigDiff from './triggerViewConfigDiff/TriggerViewConfigDiff'
5655
import Tippy from '@tippyjs/react'
57-
import { ARTIFACT_STATUS } from './Constants'
56+
import { ARTIFACT_STATUS,NO_VULNERABILITY_TEXT} from './Constants'
57+
import { ScannedByToolModal } from '../../../common/security/ScannedByToolModal'
58+
import { ModuleNameMap } from '../../../../config'
5859

5960
const ApprovalInfoTippy = importComponentFromFELibrary('ApprovalInfoTippy')
6061
const ExpireApproval = importComponentFromFELibrary('ExpireApproval')
@@ -221,15 +222,24 @@ export class CDMaterial extends Component<CDMaterialProps, CDMaterialState> {
221222
)
222223
} else if (!mat.vulnerabilitiesLoading && mat.vulnerabilities.length === 0) {
223224
return (
224-
<div className="security-tab-empty">
225-
<p className="security-tab-empty__title">No vulnerabilities Found</p>
225+
<div className="security-tab-empty summary-view__card">
226+
<p className="security-tab-empty__title">{NO_VULNERABILITY_TEXT.Secured}</p>
227+
<p>{NO_VULNERABILITY_TEXT.NoVulnerabilityFound}</p>
226228
<p className="security-tab-empty__subtitle">{mat.lastExecution}</p>
229+
<p className="workflow__header dc__border-radius-24 bcn-0">
230+
<ScannedByToolModal scanToolId={mat.scanToolId} />
231+
</p>
227232
</div>
228233
)
229234
} else
230235
return (
231236
<div className="security-tab">
232-
<p className="security-tab__last-scanned">Scanned on {mat.lastExecution} </p>
237+
<div className="flexbox dc__content-space">
238+
<span className="flex left security-tab__last-scanned ">Scanned on {mat.lastExecution} </span>
239+
<span className="flex right">
240+
<ScannedByToolModal scanToolId={mat.scanToolId} />
241+
</span>
242+
</div>
233243
<ScanVulnerabilitiesTable vulnerabilities={mat.vulnerabilities} />
234244
</div>
235245
)

0 commit comments

Comments
 (0)