Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: integrate scanning for v1 and v2 APIs #2317

Merged
merged 31 commits into from
Dec 30, 2024
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
Show all changes
31 commits
Select commit Hold shift + click to select a range
bfcf197
fix: sentry source map upload action
eshankvaish Dec 23, 2024
76fab4c
test: add test changes
eshankvaish Dec 23, 2024
2b71610
Revert "test: add test changes"
eshankvaish Dec 23, 2024
7254a7f
fix: name for step
eshankvaish Dec 23, 2024
f899302
Merge pull request #2309 from devtron-labs/fix/source-map-upload
eshankvaish Dec 23, 2024
3c8ae86
feat: integrate sacanning for v1 and v2 APIs
arunjaindev Dec 24, 2024
3465ac8
feat: remove falg for resource scan from dashbaord
arunjaindev Dec 26, 2024
aafd80e
feat: add check for progressing in security card
arunjaindev Dec 26, 2024
8dced5f
feat: remove name from scan details state
arunjaindev Dec 26, 2024
dadfb89
feat: add isManifestScanningEnabled in main context
arunjaindev Dec 26, 2024
bc66839
feat: add checks on security card
arunjaindev Dec 26, 2024
8498112
feat: use common util for scan tool, severity count and total count
arunjaindev Dec 26, 2024
952b97e
fix: update devtron-fe-common-lib to version 1.3.0-patch-3
AbhishekA1509 Dec 26, 2024
0f2bfc8
feat: uplife return statements
arunjaindev Dec 26, 2024
4affde2
Merge pull request #2321 from devtron-labs/fix/rjsf-checkbox-null-check
AbhishekA1509 Dec 26, 2024
86d471a
chore: remove image scan enabled check
arunjaindev Dec 27, 2024
5816258
Merge branch 'develop' of https://github.com/devtron-labs/dashboard i…
arunjaindev Dec 27, 2024
2b8691b
Merge branch 'develop' of https://github.com/devtron-labs/dashboard i…
arunjaindev Dec 27, 2024
644a01d
feat: use app security hook in ci detials
arunjaindev Dec 27, 2024
8032ddc
chore: update check for security-scan app security
arunjaindev Dec 27, 2024
60b1f88
chore: revert yarnlock
arunjaindev Dec 27, 2024
a90eeff
fix: loading state for global scans list
arunjaindev Dec 27, 2024
7cea9ea
chore: version bump
arunjaindev Dec 27, 2024
d04e471
feat: remove isManifestScanningEnabled flag from helm apps
arunjaindev Dec 27, 2024
6c5d202
fix: hide security card in app details and ci if image scan is null
arunjaindev Dec 27, 2024
0386a49
fix: update check for security card
arunjaindev Dec 27, 2024
d58325a
chore: version bump
arunjaindev Dec 28, 2024
2b72f6d
fix: use computedAppId for api call in security tab
arunjaindev Dec 28, 2024
7c33b24
Merge pull request #2322 from devtron-labs/fix/integrate-scans
arunjaindev Dec 30, 2024
cd941c8
Merge branch 'develop' into feat/integrate-scan
arunjaindev Dec 30, 2024
8e08c01
Merge branch 'main' of https://github.com/devtron-labs/dashboard into…
arunjaindev Dec 30, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 0 additions & 2 deletions .env
Original file line number Diff line number Diff line change
Expand Up @@ -44,9 +44,7 @@ SIDEBAR_DT_LOGO=
ENABLE_EXTERNAL_ARGO_CD=false
API_BATCH_SIZE=20
SERVICE_WORKER_TIMEOUT=3
ENABLE_RESOURCE_SCAN=false
FEATURE_USER_DEFINED_GITOPS_REPO_ENABLE=false
ENABLE_RESOURCE_SCAN_V2=false
HIDE_RELEASES=true
HIDE_RESOURCE_WATCHER=true
ORGANIZATION_NAME=
Expand Down
1 change: 0 additions & 1 deletion .eslintignore
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,6 @@ src/components/app/details/appDetails/AppStatusCard.tsx
src/components/app/details/appDetails/DeploymentStatusDetailModal.tsx
src/components/app/details/appDetails/GraphsModal.tsx
src/components/app/details/appDetails/IssuesCard.tsx
src/components/app/details/appDetails/SecurityVulnerabilityCard.tsx
src/components/app/details/appDetails/SourceInfo.tsx
src/components/app/details/appDetails/__tests__/GenericInfo.test.tsx
src/components/app/details/appDetails/index.tsx
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
"private": true,
"homepage": "/dashboard",
"dependencies": {
"@devtron-labs/devtron-fe-common-lib": "1.3.5",
"@devtron-labs/devtron-fe-common-lib": "1.3.5-beta-2",
"@esbuild-plugins/node-globals-polyfill": "0.2.3",
"@rjsf/core": "^5.13.3",
"@rjsf/utils": "^5.13.3",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,9 @@ import {
ModuleNameMap,
SecurityModal,
ResponseType,
ApiResponseResultType,
GetResourceScanDetailsPayloadType,
useAsync,
ScanResultDTO,
} from '@devtron-labs/devtron-fe-common-lib'
import DeleteResourcePopup from './DeleteResourcePopup'
import { importComponentFromFELibrary, getShowResourceScanModal } from '../../common'
Expand All @@ -39,8 +39,6 @@ import { ReactComponent as MenuDots } from '../../../assets/icons/appstatus/ic-m
import { NodeType } from '../../v2/appDetails/appDetails.type'

const OpenSecurityModalButton = importComponentFromFELibrary('OpenSecurityModalButton', null, 'function')
const isFELibAvailable = importComponentFromFELibrary('isFELibAvailable', false, 'function')
const SecurityModalSidebar = importComponentFromFELibrary('SecurityModalSidebar', null, 'function')
const getResourceScanDetails: ({
name,
namespace,
Expand All @@ -52,7 +50,7 @@ const getResourceScanDetails: ({
appType,
deploymentType,
isAppDetailView,
}: GetResourceScanDetailsPayloadType) => Promise<ResponseType<ApiResponseResultType>> = importComponentFromFELibrary(
}: GetResourceScanDetailsPayloadType) => Promise<ResponseType<ScanResultDTO>> = importComponentFromFELibrary(
'getResourceScanDetails',
null,
'function',
Expand All @@ -69,8 +67,6 @@ const ResourceBrowserActionMenu: React.FC<ResourceBrowserActionMenuType> = ({
}) => {
const { installedModuleMap } = useMainContext()

const isSecurityScanV2Enabled = window._env_.ENABLE_RESOURCE_SCAN_V2 && isFELibAvailable

const [showDeleteDialog, setShowDeleteDialog] = useState(false)
const [showVulnerabilityModal, setShowVulnerabilityModal] = useState(false)

Expand All @@ -85,7 +81,7 @@ const ResourceBrowserActionMenu: React.FC<ResourceBrowserActionMenuType> = ({
clusterId: +clusterId,
}),
[],
showVulnerabilityModal && getResourceScanDetails && isSecurityScanV2Enabled,
showVulnerabilityModal && !!getResourceScanDetails,
)

const toggleDeleteDialog = () => {
Expand All @@ -100,11 +96,10 @@ const ResourceBrowserActionMenu: React.FC<ResourceBrowserActionMenuType> = ({
setShowVulnerabilityModal(false)
}

const showResourceScanModal =
getShowResourceScanModal(
selectedResource?.gvk?.Kind as NodeType,
installedModuleMap.current?.[ModuleNameMap.SECURITY_TRIVY],
) && window._env_.ENABLE_RESOURCE_SCAN_V2
const showResourceScanModal = getShowResourceScanModal(
selectedResource?.gvk?.Kind as NodeType,
installedModuleMap.current?.[ModuleNameMap.SECURITY_TRIVY],
)

return (
<>
Expand Down Expand Up @@ -193,12 +188,9 @@ const ResourceBrowserActionMenu: React.FC<ResourceBrowserActionMenuType> = ({
/>
)}

{showVulnerabilityModal && !!isFELibAvailable && (
{showVulnerabilityModal && !!getResourceScanDetails && (
<SecurityModal
isResourceScan
handleModalClose={handleCloseVulnerabilityModal}
Sidebar={SecurityModalSidebar}
isSecurityScanV2Enabled={isSecurityScanV2Enabled}
isLoading={resourceScanLoading}
error={resourceScanError}
responseData={resourceScanResponse?.result}
Expand Down
41 changes: 7 additions & 34 deletions src/components/app/details/appDetails/AppSecurity.tsx
Original file line number Diff line number Diff line change
@@ -1,60 +1,33 @@
import {
ApiResponseResultType,
AppDetailsPayload,
getExecutionDetails,
getSeverityCountFromSummary,
getTotalSeverityCount,
ResponseType,
SeverityCount,
useAsync,
getSecurityScan,
} from '@devtron-labs/devtron-fe-common-lib'
import { importComponentFromFELibrary } from '@Components/common'
import { UseGetAppSecurityDetailsProps, UseGetAppSecurityDetailsReturnType } from './appDetails.type'

const getSecurityScan: ({
appId,
envId,
installedAppId,
}: AppDetailsPayload) => Promise<ResponseType<ApiResponseResultType>> = importComponentFromFELibrary(
'getSecurityScan',
null,
'function',
)

export const useGetAppSecurityDetails = ({
appId,
envId,
installedAppId,
artifactId,
imageScanDeployInfoId,
isSecurityScanV2Enabled,
}: UseGetAppSecurityDetailsProps): UseGetAppSecurityDetailsReturnType => {
const [scanResultLoading, scanResultResponse, scanResultError, reloadScanResult] = useAsync(
() => getSecurityScan({ appId, envId, installedAppId }),
[appId, envId, installedAppId],
getSecurityScan && isSecurityScanV2Enabled && (!!appId || !!installedAppId),
(!!appId && !!envId) || !!installedAppId,
)

const [executionDetailsLoading, executionDetailsResponse, executionDetailsError, reloadExecutionDetails] = useAsync(
() => getExecutionDetails(artifactId ? { appId, envId, artifactId } : { appId, envId, imageScanDeployInfoId }),
[appId, envId, imageScanDeployInfoId, artifactId],
!isSecurityScanV2Enabled && !!appId,
)

const scanDetailsResponse = isSecurityScanV2Enabled ? scanResultResponse : executionDetailsResponse

const severities = isSecurityScanV2Enabled
? scanResultResponse?.result.imageScan.vulnerability?.summary.severities
: executionDetailsResponse?.result.imageScan.vulnerability?.summary.severities
const severities = scanResultResponse?.result.imageScan?.vulnerability?.summary.severities
const severityCount: SeverityCount = getSeverityCountFromSummary(severities)

const totalCount = getTotalSeverityCount(severityCount)

return {
scanDetailsLoading: scanResultLoading || executionDetailsLoading,
scanDetailsResponse,
scanDetailsError: scanResultError || executionDetailsError,
reloadScanDetails: isSecurityScanV2Enabled ? reloadScanResult : reloadExecutionDetails,
scanResultLoading,
scanResultResponse,
scanResultError,
reloadScanResult,
severityCount,
totalCount,
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,7 @@

import React, { useState } from 'react'
import Tippy from '@tippyjs/react'
import {
getTotalSeverityCount,
SecurityModal,
} from '@devtron-labs/devtron-fe-common-lib'
import { getTotalSeverityCount, SecurityModal } from '@devtron-labs/devtron-fe-common-lib'
import { ReactComponent as Question } from '../../../../assets/icons/ic-help-outline.svg'
import { ReactComponent as Bug } from '../../../../assets/icons/ic-nav-bug.svg'
import { ReactComponent as Secure } from '../../../../assets/icons/ic-secure.svg'
Expand All @@ -28,32 +25,28 @@ import LoadingCard from './LoadingCard'
import { importComponentFromFELibrary } from '../../../common'
import { useGetAppSecurityDetails } from './AppSecurity'

const isFELibAvailable = importComponentFromFELibrary('isFELibAvailable', null, 'function')
const SecurityModalSidebar = importComponentFromFELibrary('SecurityModalSidebar', null, 'function')

export const SecurityVulnerabilityCard = ({
cardLoading,
appId,
envId,
installedAppId,
artifactId,
isExternalCI,
}: SecurityVulnerabilityCardType) => {
const [showScanDetailsModal, setShowScanDetailsModal] = useState<boolean>(false)
const isSecurityScanV2Enabled = window._env_.ENABLE_RESOURCE_SCAN_V2 && !!isFELibAvailable

const handleModalClose = () => setShowScanDetailsModal(false)

const { scanDetailsLoading, scanDetailsResponse, scanDetailsError, reloadScanDetails, severityCount } =
useGetAppSecurityDetails({ appId: +appId, envId: +envId, installedAppId, artifactId, isSecurityScanV2Enabled })
const { scanResultLoading, scanResultResponse, scanResultError, reloadScanResult, severityCount } =
useGetAppSecurityDetails({ appId: +appId, envId: +envId, installedAppId })

// Since we get status in v2 Api only
const imageScanFailed: boolean = isSecurityScanV2Enabled && scanDetailsResponse?.result.codeScan.status === 'Failed'
const imageScanProgressing: boolean =
isSecurityScanV2Enabled && scanDetailsResponse?.result.codeScan.status === 'Progressing'
const imageScanProgressing: boolean = scanResultResponse?.result.imageScan?.vulnerability?.list.some(
(image) => image.status === 'Running' || image.status === 'Progressing',
)
const imageScanFailed: boolean = scanResultResponse?.result.imageScan?.vulnerability?.list[0].status === 'Failed'

const handleOnCardClick = () => {
if (!cardLoading && !scanDetailsError && !showScanDetailsModal) {
if (!cardLoading && !scanResultLoading && !scanResultError && !showScanDetailsModal) {
// hack: added timeout to prevent click outside
setTimeout(() => setShowScanDetailsModal(true), 100)
}
Expand All @@ -62,14 +55,14 @@ export const SecurityVulnerabilityCard = ({
const totalCount = getTotalSeverityCount(severityCount)

const getIcon = () => {
if (scanDetailsError || imageScanFailed || imageScanProgressing || totalCount) {
if (scanResultError || imageScanFailed || imageScanProgressing || totalCount) {
return <Bug className="scy-7" />
}
return <Secure />
}

const getTitle = () => {
if (scanDetailsError) {
if (scanResultError) {
return '--'
}
if (imageScanFailed) {
Expand All @@ -79,7 +72,7 @@ export const SecurityVulnerabilityCard = ({
return <div className="f-progressing dc__loading-dots">Scanning</div>
}
if (!totalCount) {
return <div className="dc__info-title lh-20 ">You're secure!</div>
return <div className="dc__info-title lh-20 ">You&apos;re secure!</div>
}
return (
<div className="fs-13 fw-6 lh-20 f-waiting" data-testid="security-card-total-count">
Expand All @@ -89,15 +82,15 @@ export const SecurityVulnerabilityCard = ({
}

const getSubtitle = () => {
if (scanDetailsError) {
if (scanResultError) {
return 'Failed to fetch'
}
if (imageScanFailed) {
return 'Security scan failed'
}
if (imageScanProgressing) {
return 'Security scan in progress'
}
if (imageScanFailed) {
return 'Security scan failed'
}
if (!totalCount) {
return 'No Vulnerabilities found'
}
Expand All @@ -117,12 +110,13 @@ export const SecurityVulnerabilityCard = ({
}

const getActionButton = () => {
if (scanDetailsError) {
if (scanResultError) {
return (
<button
className="app-details-info-card__bottom-container__details fs-12 fw-6 dc__unset-button-styles"
onClick={reloadScanDetails}
onClick={reloadScanResult}
data-testid="security-card-handle-refetch-button"
type="button"
>
Refetch
</button>
Expand All @@ -138,19 +132,19 @@ export const SecurityVulnerabilityCard = ({
)
}

if (cardLoading || scanDetailsLoading) {
if (cardLoading || scanResultLoading) {
return <LoadingCard />
}

if (scanDetailsResponse && !scanDetailsResponse.result.scanned) {
if (scanResultResponse && !scanResultResponse.result.scanned) {
return null
}

return (
<button type="button" className="dc__unset-button-styles" onClick={handleOnCardClick}>
<div
data-testid="security-vulnerability-card"
className={`app-details-info-card flex left bcn-0 br-8 mr-12 lh-20 w-200 ${cardLoading || scanDetailsError ? '' : 'pointer'}`}
className={`app-details-info-card flex left bcn-0 br-8 mr-12 lh-20 w-200 ${cardLoading || scanResultError ? '' : 'pointer'}`}
>
<div className="app-details-info-card__top-container flex">
<div className="app-details-info-card__top-container__content">
Expand Down Expand Up @@ -188,13 +182,10 @@ export const SecurityVulnerabilityCard = ({
{showScanDetailsModal && (
<SecurityModal
handleModalClose={handleModalClose}
isExternalCI={isExternalCI}
Sidebar={SecurityModalSidebar}
isSecurityScanV2Enabled={isSecurityScanV2Enabled}
isHelmApp={!!installedAppId}
isLoading={scanDetailsLoading}
error={scanDetailsError}
responseData={scanDetailsResponse?.result}
isLoading={scanResultLoading || cardLoading}
error={scanResultError}
responseData={scanResultResponse?.result}
hidePolicy
/>
)}
Expand Down
23 changes: 12 additions & 11 deletions src/components/app/details/appDetails/SourceInfo.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -158,15 +158,18 @@ export const SourceInfo = ({
</div>
</Tooltip>
)}
{appDetails?.resourceTree && !isIsolatedEnv && window._env_.FEATURE_CONFIG_DRIFT_ENABLE && ConfigSyncStatusButton && (
<div className="pl-8">
<ConfigSyncStatusButton
areConfigurationsDrifted={appDetails.resourceTree.hasDrift}
appId={appDetails.appId}
envId={envId}
/>
</div>
)}
{appDetails?.resourceTree &&
!isIsolatedEnv &&
window._env_.FEATURE_CONFIG_DRIFT_ENABLE &&
ConfigSyncStatusButton && (
<div className="pl-8">
<ConfigSyncStatusButton
areConfigurationsDrifted={appDetails.resourceTree.hasDrift}
appId={appDetails.appId}
envId={envId}
/>
</div>
)}
{isdeploymentAppDeleting && (
<div data-testid="deleteing-argocd-pipeline" className="flex left">
<Trash className="icon-dim-16 mr-8 ml-12" />
Expand Down Expand Up @@ -364,8 +367,6 @@ export const SourceInfo = ({
cardLoading={cardLoading}
appId={params.appId}
envId={params.envId}
artifactId={ciArtifactId}
isExternalCI={isExternalCI}
/>
)}
<div className="flex right ml-auto">
Expand Down
Loading
Loading