Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
15 changes: 9 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,16 +26,18 @@ In your Github action workflow file (eg: `.github/workflows/build.yml`), insert
appknox_access_token: ${{ secrets.APPKNOX_ACCESS_TOKEN }}
file_path: app/build/outputs/apk/debug/app-debug.apk
risk_threshold: HIGH
region: Global
```

## Inputs

| Key | Value |
|-------------------------|------------------------------|
| `appknox_access_token` | Personal access token secret |
| `file_path` | File path to the mobile application binary to be uploaded |
| `risk_threshold` | Risk threshold value for which the CI should fail. <br><br>Accepted values: `CRITICAL, HIGH, MEDIUM & LOW` <br><br>Default: `LOW` |
| `sarif` | Enables SARIF report generation. <br><br>Accepted values: `Enable & Disable` <br><br>Default: `Disable` |
| Key | Value |
|------------------------|----------------------------------------------------------------------------------------------------------------------------------|
| `appknox_access_token` | Personal access token secret |
| `file_path` | File path to the mobile application binary to be uploaded |
| `risk_threshold` | Risk threshold value for which the CI should fail. <br><br>Accepted values: `CRITICAL, HIGH, MEDIUM & LOW` <br><br>Default: `LOW`|
| `sarif` | Enables SARIF report generation. <br><br>Accepted values: `Enable & Disable` <br><br>Default: `Disable` |
| `region` | The Appknox Regions to use. Can be a region like `"Global"`, `"Saudi"`. By default it is `"Global"` |

---

Expand Down Expand Up @@ -67,6 +69,7 @@ jobs:
appknox_access_token: ${{ secrets.APPKNOX_ACCESS_TOKEN }}
file_path: app/build/outputs/apk/debug/app-debug.apk
risk_threshold: MEDIUM
region: Global
```
### Appknox Scan with Downloadable SARIF File
_This example demonstrates how to run Appknox Scan to generate a SARIF report and download it as an artifact._
Expand Down
6 changes: 5 additions & 1 deletion action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ description: 'Ensure your mobile application are secure'
author: 'Appknox'
inputs:
appknox_access_token:
description: 'Pesonal Access token on Appknox'
description: 'Personal Access Token on Appknox'
required: true
file_path:
description: 'Path to the mobile application binary (apk/ipa)'
Expand All @@ -19,6 +19,10 @@ inputs:
description: 'Static scan timeout duration in minutes. If not provided defaults to 30 mins'
required: false
default: 30
region: # New input parameter
description: 'The Appknox Regions to use. Can be a region like `"Global"`, `"Saudi"`. By default it is `"Global"`'
required: false
default: 'secure.appknox.com' # Default to the standard region
branding:
icon: 'shield'
color: 'blue'
Expand Down
3 changes: 3 additions & 0 deletions src/appknox-inputs.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,11 @@ export interface AppknoxInputs {
* Enable SARIF format
*/
sarif: SarifOptions;

/**
* Timeout duration in minutes for the static scan
*/
sastTimeout: number;

region?: string; // Optional Region parameter
}
3 changes: 2 additions & 1 deletion src/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,8 @@ export enum Inputs {
Path = 'file_path',
RiskThreshold = 'risk_threshold',
Sarif = 'sarif',
SastTimeout = 'sast_timeout'
SastTimeout = 'sast_timeout',
Region = 'region' // New input for Region
}

export enum SarifOptions {
Expand Down
31 changes: 23 additions & 8 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,17 +6,32 @@ async function run(): Promise<void> {
try {
const inputs = getInputs();
core.exportVariable('APPKNOX_ACCESS_TOKEN', inputs.appknoxAccessToken);
await whoami();
const fileID = await upload(inputs.filePath);
const sarif = inputs.sarif;
const sastTimeout=inputs.sastTimeout;
if (sarif == 'Enable'){
await sarifReport(fileID);

// Log the region value
core.info(`Region: ${inputs.region}`);

// Set the Region if provided
if (inputs.region) {
core.exportVariable('APPKNOX_REGION', inputs.region);
}

// Ensure Region is used in the whoami function or any other function that requires it
await whoami(inputs.region);

// Upload file and get file ID
const fileID = await upload(inputs.filePath, inputs.region);

// Generate SARIF report if enabled
if (inputs.sarif === 'Enable') {
await sarifReport(fileID, inputs.region);
}
await cicheck(inputs.riskThreshold, fileID, sastTimeout);

// Run CICheck with the specified risk threshold
await cicheck(inputs.riskThreshold, fileID, sastTimeout, inputs.region);

} catch (err: any) {
core.setFailed(err.message);
}
}

run();
run();
5 changes: 4 additions & 1 deletion src/input-helper.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,12 +37,15 @@ export function getInputs(): AppknoxInputs {
)}`
);
}

const region = core.getInput(Inputs.Region) || 'secure.appknox.com'; // Default to the standard Region
const inputs = {
appknoxAccessToken: accessToken,
filePath: path,
riskThreshold: riskThreshold,
sarif: sarifString,
sastTimeout: sastTimeout
sastTimeout: sastTimeout,
region: region
} as AppknoxInputs;

return inputs;
Expand Down
39 changes: 28 additions & 11 deletions src/tool.ts
Original file line number Diff line number Diff line change
Expand Up @@ -61,15 +61,30 @@ interface ExecOutput {

async function execBinary(
path: string,
args: Array<string>
args: Array<string>,
region?: string // Optional region parameter
): Promise<ExecOutput> {
let output = '';
let err = '';

const filteredEnv: { [key: string]: string } = {};
for (const key in process.env) {
if (process.env[key] !== undefined) {
filteredEnv[key] = process.env[key] as string;
}
}

// Add the Region to the environment if provided
if (region) {
filteredEnv['APPKNOX_REGION'] = region;
}

const options = {
listeners: {},
ignoreReturnCode: true
ignoreReturnCode: true,
env: filteredEnv // Use the filtered environment variables
};

options.listeners = {
stdout: (data: Buffer) => {
output += data.toString();
Expand All @@ -86,17 +101,17 @@ async function execBinary(
};
}

export async function whoami(): Promise<void> {
export async function whoami(region?: string): Promise<void> {
const toolPath = await getAppknoxToolPath();
const combinedOutput = await execBinary(toolPath, ['whoami']);
const combinedOutput = await execBinary(toolPath, ['whoami'], region);
if (combinedOutput.err.indexOf('Invalid token') > -1) {
throw new Error('Invalid token');
}
}

export async function upload(file_path: string): Promise<number> {
export async function upload(file_path: string, region?: string): Promise<number> {
const toolPath = await getAppknoxToolPath();
const combinedOutput = await execBinary(toolPath, ['upload', file_path]);
const combinedOutput = await execBinary(toolPath, ['upload', file_path],region);
if (combinedOutput.code > 0) {
const errArr = combinedOutput.err.split('\n').filter(_ => _);
throw new Error(errArr[errArr.length - 1]);
Expand All @@ -105,14 +120,15 @@ export async function upload(file_path: string): Promise<number> {
}

export async function sarifReport(
fileID: number
fileID: number,
region?: string
): Promise<ExecOutput> {
const toolPath = await getAppknoxToolPath();
const args = [
'sarif',
fileID.toString(),
];
const combinedOutput = await execBinary(toolPath, args);
const combinedOutput = await execBinary(toolPath, args, region);
if (combinedOutput.code > 0) {
const errArr = combinedOutput.err.split('\n').filter(_ => _);
const outArr = combinedOutput.output.split('\n').filter(_ => _);
Expand All @@ -126,7 +142,8 @@ export async function sarifReport(
export async function cicheck(
riskThreshold: RiskThresholdOptions,
fileID: number,
sastTimeout: number
sastTimeout: number,
region?: string
): Promise<void> {
const toolPath = await getAppknoxToolPath();
const args = [
Expand All @@ -137,12 +154,12 @@ export async function cicheck(
'--timeout',
sastTimeout.toString()
];
const combinedOutput = await execBinary(toolPath, args);
const combinedOutput = await execBinary(toolPath, args, region);
if (combinedOutput.code > 0) {
const errArr = combinedOutput.err.split('\n').filter(_ => _);
const outArr = combinedOutput.output.split('\n').filter(_ => _);
const errMes = errArr[errArr.length - 1];
const outMes = outArr[outArr.length - 1];
throw new Error(errMes + '. ' + outMes);
}
}
}