Skip to content
This repository has been archived by the owner on Aug 16, 2024. It is now read-only.

Commit

Permalink
IA: 153 filter params added
Browse files Browse the repository at this point in the history
  • Loading branch information
Bharatkk-metron committed Jul 22, 2024
1 parent 29be46f commit 3c9cfd7
Show file tree
Hide file tree
Showing 8 changed files with 169 additions and 24 deletions.
17 changes: 16 additions & 1 deletion .env.example
Original file line number Diff line number Diff line change
@@ -1,3 +1,18 @@
BASE_URL=
API_TOKEN=
ENABLE_FINDINGS_INGESTION=
ENABLE_FINDINGS_INGESTION=true/false
SEVERITIES=INFO,MINOR,MAJOR,CRITICAL,BLOCKER
# JUST FOR INFO:
# INFO, MINOR -> LOW in API Version 2
# MAJOR -> MEDIUM in API Version 2
# CRITICAL BLOCKERS -> HIGH in API Version 2
STATUS=OPEN,CONFIRMED,REOPENED,RESOLVED,CLOSED # 0 or more values you can pass from given values
CREATED_IN_LAST=10d # default value is 10 days
#createdInLast: optional
#To retrieve issues created during a time span before the current time (exclusive). Accepted units are 'y' for year, 'm' for month, 'w' for week and 'd' for day. If this parameter is set, createdAfter must not be set
# Example value: 1m2w (1 month 2 weeks)
TYPES=CODE_SMELL,BUG,VULNERABILITY # 0 or more values you can pass from given values
# JUST FOR INFO:
# CODE_SMELL -> MAINTAINABILITY in API Version 2
# BUG -> RELIABILITY in API Version 2
# VULNERABILITY: SECURITY in API Version 2
6 changes: 3 additions & 3 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ jobs:
strategy:
fail-fast: false
matrix:
node-version: [14.x]
node-version: [18.x]
os: [ubuntu-latest]

steps:
Expand Down Expand Up @@ -38,13 +38,13 @@ jobs:
strategy:
fail-fast: false
matrix:
node: [14]
node: [18]

steps:
- name: Setup Node
uses: actions/setup-node@v1
with:
node-version: 14.x
node-version: 18.x

- name: Check out repo
uses: actions/checkout@v2
Expand Down
2 changes: 1 addition & 1 deletion Dockerfile
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
FROM node:14-alpine
FROM node:18-alpine

ENV JUPITERONE_INTEGRATION_DIR=/opt/jupiterone/integration

Expand Down
12 changes: 6 additions & 6 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -31,15 +31,15 @@
"prepack": "yarn build"
},
"peerDependencies": {
"@jupiterone/integration-sdk-core": "^8.30.0"
"@jupiterone/integration-sdk-core": "^13.2.0"
},
"devDependencies": {
"@jupiterone/integration-sdk-core": "^8.30.0",
"@jupiterone/integration-sdk-dev-tools": "^8.30.0",
"@jupiterone/integration-sdk-testing": "^8.30.0",
"@types/node-fetch": "^2.5.10"
"@jupiterone/integration-sdk-core": "^13.2.0",
"@jupiterone/integration-sdk-dev-tools": "^13.2.0",
"@jupiterone/integration-sdk-testing": "^13.2.0",
"@types/node-fetch": "^2.6.11"
},
"dependencies": {
"node-fetch": "^2.6.1"
"node-fetch": "^3.3.2"
}
}
20 changes: 20 additions & 0 deletions src/instanceConfigFields.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,26 @@ const instanceConfigFields: IntegrationInstanceConfigFieldMap = {
mask: false,
optional: true,
},
severities: {
type: 'string',
mask: false,
optional: true,
},
status: {
type: 'string',
mask: false,
optional: true,
},
createdInLast: {
type: 'string',
mask: false,
optional: true,
},
types: {
type: 'string',
mask: false,
optional: true,
},
};

export default instanceConfigFields;
32 changes: 32 additions & 0 deletions src/steps/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,38 @@ import { RelationshipClass } from '@jupiterone/integration-sdk-core';

export const ACCOUNT_ENTITY_KEY = 'sonarqube:account';

export const FINDINGS_SEVERITIES = {
INFO: 'LOW',
MINOR: 'MEDIUM',
MAJOR: 'MEDIUM',
CRITICAL: 'HIGH',
BLOCKER: 'HIGH',
};

export const V1_SEVERITIES_VALUES = [
'INFO',
'MINOR',
'MAJOR',
'CRITICAL',
'BLOCKER',
];
export const V2_SEVERITIES_VALUES = ['LOW', 'MEDIUM', 'HIGH'];
export const DEFAULT_CREATED_IN_LAST = '10d';

export const FINDING_STATUSES = {
OPEN: 'OPEN',
CONFIRMED: 'CONFIRMED',
REOPENED: 'FALSE_POSITIVE',
RESOLVED: 'ACCEPTED',
CLOSED: 'FIXED',
};

export const FINDING_TYPES = {
CODE_SMELL: 'MAINTAINABILITY',
BUG: 'RELIABILITY',
VULNERABILITY: 'SECURITY',
};

export const Steps = {
ACCOUNT: 'fetch-account',
PROJECTS: 'fetch-projects',
Expand Down
100 changes: 87 additions & 13 deletions src/steps/finding/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,70 @@ import {
RelationshipClass,
} from '@jupiterone/integration-sdk-core';

import { Entities, Relationships, Steps } from '../constants';
import {
DEFAULT_CREATED_IN_LAST,
Entities,
FINDING_STATUSES,
FINDING_TYPES,
FINDINGS_SEVERITIES,
Relationships,
Steps,
V1_SEVERITIES_VALUES,
V2_SEVERITIES_VALUES,
} from '../constants';
import { createSonarqubeClient } from '../../provider';
import { SonarqubeIntegrationConfig } from '../../types';
import { SonarqubeProject } from '../../provider/types/v1';
import { createFindingEntity } from './converter';
import {
createFindingEntity,
createFindingEntityIdentifier,
} from './converter';
import { APIVersion } from '../../provider/types/common';
import { createProjectEntityIdentifier } from '../project/converter';

async function getSeverities(instanceConfig: SonarqubeIntegrationConfig) {
const { severities, apiVersion } = instanceConfig;
const severitiesSet = new Set(
severities?.split(',').map((severity) => FINDINGS_SEVERITIES[severity]),
);

// V2 -> 10.4 or above version
if (apiVersion == APIVersion.V1) {
return severitiesSet.size === 0
? V1_SEVERITIES_VALUES
: Array.from(severitiesSet);
}
return severitiesSet.size === 0
? V2_SEVERITIES_VALUES
: Array.from(severitiesSet);
}

const severityList = ['INFO', 'MINOR', 'MAJOR', 'CRITICAL', 'BLOCKER'];
async function getFilterParams(instanceConfig: SonarqubeIntegrationConfig) {
const { apiVersion, status, createdInLast, types } = instanceConfig;

let filterParams;

if (apiVersion === APIVersion.V1) {
// V1 -> below 10.4 version
filterParams = {
status,
types,
};
} else {
const statusesSet = new Set(
status?.split(',').map((status) => FINDING_STATUSES[status]),
);
const typesSet = new Set(
types?.split(',').map((type) => FINDING_TYPES[type]),
);
filterParams = {
issueStatuses: Array.from(statusesSet).join(','),
impactSoftwareQualities: Array.from(typesSet).join(','),
};
filterParams['createdInLast'] = createdInLast || DEFAULT_CREATED_IN_LAST;
return filterParams;
}
}

export async function fetchFindings({
instance,
Expand All @@ -21,6 +78,9 @@ export async function fetchFindings({
}: IntegrationStepExecutionContext<SonarqubeIntegrationConfig>) {
const client = createSonarqubeClient(instance.config, logger);

const severities = await getSeverities(instance.config);
const filerParams = await getFilterParams(instance.config);

await jobState.iterateEntities(
{ _type: Entities.PROJECT._type },
async (projectEntity) => {
Expand All @@ -34,24 +94,38 @@ export async function fetchFindings({
// We need to further filter our API calls in order to minimize the chances
// we'll hit the 10,000 limit impose by the API. We're currently filtering
// by project and severity.
for (const severity of severityList) {
for (const severity of severities) {
if (instance.config.apiVersion == APIVersion.V1) {
filerParams['severities'] = severity;
} else {
filerParams['impactSeverities'] = severity;
}

await client.iterateProjectFindings(
async (finding) => {
const findingEntity = createFindingEntity(finding);

if (!(await jobState.hasKey(findingEntity._key))) {
if (!jobState.hasKey(findingEntity._key)) {
await jobState.addEntity(findingEntity);
}

await jobState.addRelationship(
createDirectRelationship({
_class: RelationshipClass.HAS,
from: projectEntity,
to: findingEntity,
}),
);
if (
!jobState.hasKey(
`${createProjectEntityIdentifier(
project.key,
)}|has|${createFindingEntityIdentifier(finding.key)}`,
)
) {
await jobState.addRelationship(
createDirectRelationship({
_class: RelationshipClass.HAS,
from: projectEntity,
to: findingEntity,
}),
);
}
},
{ componentKeys: project.key, severities: severity },
{ componentKeys: project.key, ...filerParams },
);
}
},
Expand Down
4 changes: 4 additions & 0 deletions src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,4 +14,8 @@ export interface SonarqubeIntegrationConfig extends IntegrationInstanceConfig {
* where the parameter {@param endpointVersion} determines the url to query
*/
apiVersion: APIVersion;
severities?: string;
status?: string;
createdInLast?: string;
types?: string;
}

0 comments on commit 3c9cfd7

Please sign in to comment.