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

Appknox Region #8

Open
wants to merge 18 commits into
base: main
Choose a base branch
from
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 @@ -15,6 +15,10 @@ inputs:
sarif:
description: 'Enable SARIF format report. Defaults to false'
default: 'Disable'
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
1 change: 1 addition & 0 deletions src/appknox-inputs.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,4 +20,5 @@ export interface AppknoxInputs {
* Enable SARIF format
*/
sarif: SarifOptions;
region?: string; // Optional Region parameter
}
6 changes: 6 additions & 0 deletions src/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,12 @@ export enum Inputs {
Path = 'file_path',
RiskThreshold = 'risk_threshold',
Sarif = 'sarif',
Region = 'region' // New input for Region
}

export enum SarifOptions {
Enable = 'Enable',
Disable = 'Disable'
}

export enum SarifOptions {
Expand Down
30 changes: 23 additions & 7 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,16 +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;
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);

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

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

run();
run();
6 changes: 5 additions & 1 deletion src/input-helper.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,11 +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
sarif: sarifString,
region: region // Include the region in the inputs
} as AppknoxInputs;

return inputs;
}
39 changes: 28 additions & 11 deletions src/tool.ts
Original file line number Diff line number Diff line change
Expand Up @@ -59,15 +59,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 @@ -84,17 +99,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 @@ -103,14 +118,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 @@ -123,7 +139,8 @@ export async function sarifReport(

export async function cicheck(
riskThreshold: RiskThresholdOptions,
fileID: number
fileID: number,
region?: string
): Promise<void> {
const toolPath = await getAppknoxToolPath();
const args = [
Expand All @@ -132,12 +149,12 @@ export async function cicheck(
'--risk-threshold',
riskThreshold
];
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);
}
}
}