Skip to content

Commit 9fd41ce

Browse files
Adding unit tests (#14)
<!-- Thank you for proposing a pull request! Please note that SOME TESTS WILL LIKELY FAIL due to how GitHub exposes secrets in Pull Requests from forks. Someone from the team will review your Pull Request and respond. Please describe your change and any implementation details below. --> --------- Co-authored-by: Adish Agarwal <[email protected]>
1 parent f892789 commit 9fd41ce

File tree

16 files changed

+910
-61
lines changed

16 files changed

+910
-61
lines changed

.github/workflows/test.yml

Lines changed: 15 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,9 @@ jobs:
3737
unit:
3838
name: 'unit'
3939
runs-on: 'ubuntu-latest'
40+
permissions:
41+
contents: 'read'
42+
id-token: 'write'
4043

4144
steps:
4245
- uses: 'actions/checkout@v4'
@@ -50,6 +53,11 @@ jobs:
5053

5154
- name: 'npm lint'
5255
run: 'npm run lint'
56+
57+
- uses: 'google-github-actions/auth@v2'
58+
with:
59+
workload_identity_provider: 'projects/111685897256/locations/global/workloadIdentityPools/github/providers/my-repo'
60+
service_account: '[email protected]'
5361

5462
- name: 'npm test'
5563
run: 'npm run test'
@@ -84,7 +92,7 @@ jobs:
8492
with:
8593
organization_id: '${{ env.ORGANIZATION_ID }}'
8694
# plan file has 1 CRITICAL, 2 LOW severity vulnerabilites
87-
scan_file_ref: 'test/resources/with-violations-tf_plan.json'
95+
scan_file_ref: 'tests/resources/with-violations-tf_plan.json'
8896
iac_type: 'terraform'
8997
iac_version: '1.0.0'
9098
failure_criteria: 'CRITICAL:2, Operator:OR'
@@ -93,7 +101,7 @@ jobs:
93101
scan_timeout: '1m'
94102
- name: 'Check scan result and compare sarif report generated.'
95103
run: |
96-
report_expected="test/resources/sarif.json"
104+
report_expected="tests/resources/sarif.json"
97105
report_generated="${{ steps.violations-found.outputs.iac_scan_result_sarif_path }}"
98106
if cmp -s "$report_expected" "$report_generated"; then
99107
exit 1
@@ -108,7 +116,7 @@ jobs:
108116
# uses: './'
109117
# with:
110118
# organization_id: '${{ env.ORGANIZATION_ID }}'
111-
# scan_file_ref: 'test/resources/no-violations-tf_plan.json'
119+
# scan_file_ref: 'tests/resources/no-violations-tf_plan.json'
112120
# iac_type: 'terraform'
113121
# iac_version: '1.0.0'
114122
# failure_criteria: 'CRITICAL:2, Operator:OR'
@@ -127,7 +135,7 @@ jobs:
127135
with:
128136
organization_id: '${{ env.ORGANIZATION_ID }}'
129137
# plan file has 1 CRITICAL, 2 LOW severity vulnerabilites
130-
scan_file_ref: 'test/resources/with-violations-tf_plan.json'
138+
scan_file_ref: 'tests/resources/with-violations-tf_plan.json'
131139
iac_type: 'terraform'
132140
iac_version: '1.0.0'
133141
failure_criteria: 'CRITICAL:1, Operator:OR'
@@ -147,7 +155,7 @@ jobs:
147155
with:
148156
organization_id: '${{ env.ORGANIZATION_ID }}'
149157
# plan file has 1 CRITICAL, 2 LOW severity vulnerabilites
150-
scan_file_ref: 'test/resources/with-violations-tf_plan.json'
158+
scan_file_ref: 'tests/resources/with-violations-tf_plan.json'
151159
iac_type: 'terraform'
152160
iac_version: '1.0.0'
153161
ignore_violations: 'true'
@@ -164,7 +172,7 @@ jobs:
164172
with:
165173
# Invalid org id, will cause an internal error in action
166174
organization_id: 'invalid-id'
167-
scan_file_ref: 'test/resources/with-violations-tf_plan.json'
175+
scan_file_ref: 'tests/resources/with-violations-tf_plan.json'
168176
iac_type: 'terraform'
169177
iac_version: '1.0.0'
170178
continue-on-error: true
@@ -182,7 +190,7 @@ jobs:
182190
uses: './'
183191
with:
184192
organization_id: 'invalid-id'
185-
scan_file_ref: 'test/resources/with-violations-tf_plan.json'
193+
scan_file_ref: 'tests/resources/with-violations-tf_plan.json'
186194
iac_type: 'terraform'
187195
iac_version: '1.0.0'
188196
fail_silently: 'true'

bin/runTests.sh

Lines changed: 0 additions & 19 deletions
This file was deleted.

dist/main/index.js

Lines changed: 4 additions & 4 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package-lock.json

Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
"build": "ncc build -m src/main.ts -o dist/main",
88
"lint": "eslint . --ext .ts,.tsx",
99
"format": "prettier --write **/*.ts",
10-
"test": "bash ./bin/runTests.sh"
10+
"test": "node --require ts-node/register --test-reporter spec --test tests/accessor.test.ts tests/iac_scan_report_processor.test.ts tests/utils.test.ts"
1111
},
1212
"repository": {
1313
"type": "git",

src/accessor.ts

Lines changed: 6 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -19,12 +19,7 @@ import { GoogleAuth } from 'google-auth-library';
1919
import { debug as logDebug } from '@actions/core';
2020
import { errorMessage, toBase64, fromBase64 } from '@google-github-actions/actions-utils';
2121

22-
import {
23-
MAX_RETRIES_FOR_INITIATE_SCAN,
24-
MAX_RETRIES_FOR_POLLING,
25-
RETRIABLE_ERROR_CODES,
26-
VALIDATE_ENDPOINT_PATH,
27-
} from './commons/http_config';
22+
import { RETRIABLE_ERROR_CODES, VALIDATE_ENDPOINT_PATH } from './commons/http_config';
2823
import { IACValidationException } from './exception';
2924
import { SCAN_FILE_MAX_SIZE_BYTES, USER_AGENT } from './commons/constants';
3025

@@ -155,7 +150,6 @@ export class IACAccessor {
155150
private async request(
156151
method: string,
157152
url: string,
158-
maxRetries: number,
159153
errorMsg: string,
160154
data?: any, // eslint-disable-line @typescript-eslint/no-explicit-any
161155
) {
@@ -167,7 +161,7 @@ export class IACAccessor {
167161
'Content-Type': 'application/json',
168162
};
169163

170-
while (this.shouldRetry(this.retryCount, maxRetries)) {
164+
while (this.shouldRetry()) {
171165
try {
172166
const intervalMs: number = Math.pow(2, this.retryCount) * 1000;
173167
this.retryCount++;
@@ -176,7 +170,7 @@ export class IACAccessor {
176170
const body = await response.readBody();
177171
const statusCode = response.message.statusCode || 500;
178172

179-
if (RETRIABLE_ERROR_CODES.includes(statusCode) && this.retryCount != maxRetries) {
173+
if (RETRIABLE_ERROR_CODES.includes(statusCode)) {
180174
await new Promise((resolve) => setTimeout(resolve, intervalMs));
181175
continue;
182176
}
@@ -200,10 +194,7 @@ export class IACAccessor {
200194
throw new IACValidationException(/* statusCode= */ 500, `Operation timed out`);
201195
}
202196

203-
private shouldRetry(retryCount: number, maxRetryCount: number): boolean {
204-
if (retryCount >= maxRetryCount) {
205-
return false;
206-
}
197+
private shouldRetry(): boolean {
207198
const currentTime = new Date().getTime();
208199
return currentTime < this.scanStartTime + this.scanTimeOut;
209200
}
@@ -222,7 +213,7 @@ export class IACAccessor {
222213
throw new IACValidationException(
223214
/* statusCode= */ 500,
224215
`[Internal Error] Validation Service Endpoint Returned
225-
invalid violations with one or more missing key Attributes, policyID : ${violation.policyId}, assetId : ${violation.assetId}`,
216+
invalid violations with one or more missing key Attributes, policyID : ${violation.policyId ?? ''}, assetId : ${violation.assetId ?? ''}`,
226217
);
227218
}
228219
});
@@ -276,9 +267,8 @@ export class IACAccessor {
276267
* @param name Name of the operation, of the format `operations/{name}`.
277268
*/
278269
private async pollOperation(name: string): Promise<Operation> {
279-
while (this.retryCount < MAX_RETRIES_FOR_POLLING) {
270+
while (this.shouldRetry()) {
280271
const intervalMs: number = Math.pow(2, this.retryCount) * 1000;
281-
this.retryCount++;
282272
const resp = await this.getOperation(name);
283273
if (resp && resp.done) {
284274
return resp;
@@ -299,7 +289,6 @@ export class IACAccessor {
299289
const resp: Operation = await this.request(
300290
'GET',
301291
u,
302-
MAX_RETRIES_FOR_POLLING,
303292
/*errorMsg=*/ 'encountered error while performing scan operation',
304293
);
305294
return resp;
@@ -326,7 +315,6 @@ export class IACAccessor {
326315
const resp: Operation = await this.request(
327316
'POST',
328317
u,
329-
MAX_RETRIES_FOR_INITIATE_SCAN,
330318
/*errorMsg=*/ 'encountered error while requesting scan',
331319
body,
332320
);

src/commons/http_config.ts

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,5 +18,3 @@ export const VALIDATE_ENDPOINT_DOMAIN = 'https://securityposture.googleapis.com/
1818
export const VALIDATE_ENDPOINT_PATH = (orgId: string) =>
1919
`/organizations/${orgId}/locations/global/reports:createIaCValidationReport`;
2020
export const RETRIABLE_ERROR_CODES = [408, 429, 500, 502, 503, 504];
21-
export const MAX_RETRIES_FOR_INITIATE_SCAN = 3;
22-
export const MAX_RETRIES_FOR_POLLING = 50;

src/main.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,7 @@ const version = require('../package.json').version;
6161
async function run(): Promise<void> {
6262
logInfo(`IaC Scanning Action invoked`);
6363
try {
64-
const organizationId = getInput(ORGANIZATION_ID_CONFIG_KEY, { required: true });
64+
const organizationID = getInput(ORGANIZATION_ID_CONFIG_KEY, { required: true });
6565
const scanFileRef = getInput(SCAN_FILE_REF_CONFIG_KEY, { required: true });
6666
const iacType = getInput(IAC_TYPE_CONFIG_KEY, { required: true });
6767
const iacVersion = getInput(IAC_VERSION_CONFIG_KEY, { required: true });
@@ -92,7 +92,7 @@ async function run(): Promise<void> {
9292
const scanStartTime = new Date().getTime();
9393
const accessor = new IACAccessor(
9494
VALIDATE_ENDPOINT_DOMAIN,
95-
organizationId,
95+
organizationID,
9696
scanTimeoutMs,
9797
scanStartTime,
9898
version,

src/utils.ts

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -126,17 +126,17 @@ function validateAndExtractFailureCriteriaFromMap(
126126
keyValueMap.forEach((value, key) => {
127127
if (isValidOperatorKey(key)) {
128128
if (operator) {
129-
throw new Error(`multiple operators found.`);
129+
throw new Error(`multiple operators found`);
130130
}
131131
operator = extractOperatorValue(value);
132132
return;
133133
}
134134
const severity: Severity = extractSeverityKey(
135135
key,
136-
/** errMsg= */ `invalid key: ${key}, value: ${value} pair found.`,
136+
/** errMsg= */ `invalid key: ${key}, value: ${value} pair found`,
137137
);
138138
if (violationsThresholdBySeverity.has(severity)) {
139-
throw new Error(`multiple severities of type ${key} found.`);
139+
throw new Error(`multiple severities of type ${key} found`);
140140
}
141141
if (isNaN(+value)) {
142142
throw new Error(`invalid severity count`);
@@ -145,10 +145,10 @@ function validateAndExtractFailureCriteriaFromMap(
145145
});
146146

147147
if (!operator) {
148-
throw new Error('no operator found.');
148+
throw new Error('no operator found');
149149
}
150150
if (violationsThresholdBySeverity.size == 0) {
151-
throw new Error('no severity mentioned in operator.');
151+
throw new Error('no severity mentioned');
152152
}
153153
return {
154154
violationsThresholdBySeverity: violationsThresholdBySeverity,

0 commit comments

Comments
 (0)