Skip to content

Commit

Permalink
Merge pull request #103 from microsoft/latest
Browse files Browse the repository at this point in the history
Latest
  • Loading branch information
sethRait committed Jul 25, 2024
2 parents d16b24e + a50dd3d commit 7390911
Show file tree
Hide file tree
Showing 26 changed files with 343 additions and 396 deletions.
14 changes: 4 additions & 10 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ steps:
- uses: actions/checkout@v3

- name: Run Microsoft Security DevOps
uses: microsoft/security-devops-action@v1
uses: microsoft/security-devops-action@latest
id: msdo
```

Expand All @@ -50,17 +50,10 @@ To upload results to the Security tab of your repo, run the `github/codeql-actio

## Advanced

To configure **Container Mapping** to send to **Microsoft Defender for DevOps**, include `container-mapping` as a tool:
```yaml
- uses: microsoft/security-devops-action@v1
id: msdo
with:
includeTools: container-mapping
```
To only run specific analyzers, use the `tools` command. This command is a comma-seperated list of tools to run. For example, to run only the `container-mapping` tool, configure this action as follows:

This will run all the analyzers defined by the configured or defaulted policy in addition to `container-mapping`. To only run this feature, define `container-mapping` as the only `tool` to run:
```yaml
- uses: microsoft/security-devops-action@v1
- uses: microsoft/security-devops-action@latest
id: msdo
with:
tools: container-mapping
Expand All @@ -77,6 +70,7 @@ This will run all the analyzers defined by the configured or defaulted policy in
| [Template Analyzer](https://github.com/Azure/template-analyzer) | Infrastructure-as-code (IaC), ARM templates, Bicep files | [MIT License](https://github.com/Azure/template-analyzer/blob/main/LICENSE.txt) |
| [Terrascan](https://github.com/accurics/terrascan) | Infrastructure-as-code (IaC), Terraform (HCL2), Kubernetes (JSON/YAML), Helm v3, Kustomize, Dockerfiles, Cloudformation | [Apache License 2.0](https://github.com/accurics/terrascan/blob/master/LICENSE) |
| [Trivy](https://github.com/aquasecurity/trivy) | container images, file systems, and git repositories | [Apache License 2.0](https://github.com/aquasecurity/trivy/blob/main/LICENSE) |
| [container-mapping](https://learn.microsoft.com/en-us/azure/defender-for-cloud/container-image-mapping) | container images and registries (only available for DevOps security enabled CSPM plans) | [MIT License](https://github.com/microsoft/security-devops-action/blob/main/LICENSE) |

# More Information

Expand Down
10 changes: 2 additions & 8 deletions action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,7 @@ branding:
color: 'black'
inputs:
command:
description: The command to run. Defaults to run.
default: all
options:
- all
- run
- pre-job
- post-job
description: Deprecated, do not use.
config:
description: A file path to a .gdnconfig file.
policy:
Expand All @@ -25,7 +19,7 @@ inputs:
tools:
description: A comma separated list of analyzer to run. Example bandit, binskim, container-mapping, eslint, templateanalyzer, terrascan, trivy.
includeTools:
description: A comma separated list of analyzers to run in addition to the default set defined by the policy. Limited to container-mapping
description: Deprecated
outputs:
sarifFile:
description: A file path to a SARIF results file.
Expand Down
89 changes: 78 additions & 11 deletions lib/container-mapping.js
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,8 @@ const core = __importStar(require("@actions/core"));
const exec = __importStar(require("@actions/exec"));
const os = __importStar(require("os"));
const sendReportRetryCount = 1;
const GetScanContextURL = "https://dfdinfra-afdendpoint-prod-d5fqbucbg7fue0cf.z01.azurefd.net/github/v1/auth-push/GetScanContext?context=authOnly";
const ContainerMappingURL = "https://dfdinfra-afdendpoint-prod-d5fqbucbg7fue0cf.z01.azurefd.net/github/v1/container-mappings";
class ContainerMapping {
constructor() {
this.succeedOnError = true;
Expand Down Expand Up @@ -90,6 +92,20 @@ class ContainerMapping {
dockerEvents: [],
dockerImages: []
};
let bearerToken = yield core.getIDToken()
.then((token) => { return token; })
.catch((error) => {
throw new Error("Unable to get token: " + error);
});
if (!bearerToken) {
throw new Error("Empty OIDC token received");
}
var callerIsOnboarded = yield this.checkCallerIsCustomer(bearerToken, sendReportRetryCount);
if (!callerIsOnboarded) {
core.info("Client is not onboarded to Defender for DevOps. Skipping container mapping workload.");
return;
}
core.info("Client is onboarded for container mapping.");
let dockerVersionOutput = yield exec.getExecOutput('docker --version');
if (dockerVersionOutput.exitCode != 0) {
core.info(`Unable to get docker version: ${dockerVersionOutput}`);
Expand All @@ -106,14 +122,6 @@ class ContainerMapping {
throw new Error("Unable to get docker images: " + error);
});
core.debug("Finished data collection, starting API calls.");
let bearerToken = yield core.getIDToken()
.then((token) => { return token; })
.catch((error) => {
throw new Error("Unable to get token: " + error);
});
if (!bearerToken) {
throw new Error("Empty OIDC token received");
}
var reportSent = yield this.sendReport(JSON.stringify(reportData), bearerToken, sendReportRetryCount);
if (!reportSent) {
throw new Error("Unable to send report to backend service");
Expand Down Expand Up @@ -160,7 +168,6 @@ class ContainerMapping {
return __awaiter(this, void 0, void 0, function* () {
return new Promise((resolve, reject) => __awaiter(this, void 0, void 0, function* () {
let apiTime = new Date().getMilliseconds();
let url = "https://dfdinfra-afdendpoint-prod-d5fqbucbg7fue0cf.z01.azurefd.net/github/v1/container-mappings";
let options = {
method: 'POST',
timeout: 2500,
Expand All @@ -170,8 +177,8 @@ class ContainerMapping {
'Content-Length': data.length
}
};
core.debug(`${options['method'].toUpperCase()} ${url}`);
const req = https.request(url, options, (res) => {
core.debug(`${options['method'].toUpperCase()} ${ContainerMappingURL}`);
const req = https.request(ContainerMappingURL, options, (res) => {
let resData = '';
res.on('data', (chunk) => {
resData += chunk.toString();
Expand All @@ -197,5 +204,65 @@ class ContainerMapping {
}));
});
}
checkCallerIsCustomer(bearerToken, retryCount = 0) {
return __awaiter(this, void 0, void 0, function* () {
return yield this._checkCallerIsCustomer(bearerToken)
.then((statusCode) => __awaiter(this, void 0, void 0, function* () {
if (statusCode == 200) {
return true;
}
else if (statusCode == 403) {
return false;
}
else {
core.debug(`Unexpected status code: ${statusCode}`);
return yield this.retryCall(bearerToken, retryCount);
}
}))
.catch((error) => __awaiter(this, void 0, void 0, function* () {
core.info(`Unexpected error: ${error}.`);
return yield this.retryCall(bearerToken, retryCount);
}));
});
}
retryCall(bearerToken, retryCount) {
return __awaiter(this, void 0, void 0, function* () {
if (retryCount == 0) {
core.info(`All retries failed.`);
return false;
}
else {
core.info(`Retrying checkCallerIsCustomer.\nRetry count: ${retryCount}`);
retryCount--;
return yield this.checkCallerIsCustomer(bearerToken, retryCount);
}
});
}
_checkCallerIsCustomer(bearerToken) {
return __awaiter(this, void 0, void 0, function* () {
return new Promise((resolve, reject) => __awaiter(this, void 0, void 0, function* () {
let options = {
method: 'GET',
timeout: 2500,
headers: {
'Content-Type': 'application/json',
'Authorization': 'Bearer ' + bearerToken,
}
};
core.debug(`${options['method'].toUpperCase()} ${GetScanContextURL}`);
const req = https.request(GetScanContextURL, options, (res) => {
res.on('end', () => {
resolve(res.statusCode);
});
res.on('data', function (d) {
});
});
req.on('error', (error) => {
reject(new Error(`Error calling url: ${error}`));
});
req.end();
}));
});
}
}
exports.ContainerMapping = ContainerMapping;
131 changes: 0 additions & 131 deletions lib/index.js

This file was deleted.

22 changes: 19 additions & 3 deletions lib/main.js
Original file line number Diff line number Diff line change
Expand Up @@ -33,14 +33,30 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
};
Object.defineProperty(exports, "__esModule", { value: true });
const core = __importStar(require("@actions/core"));
const index_1 = require("./index");
const msdo_1 = require("./msdo");
const msdo_interface_1 = require("./msdo-interface");
const common = __importStar(require("@microsoft/security-devops-actions-toolkit/msdo-common"));
const msdo_helpers_1 = require("./msdo-helpers");
const runner = msdo_helpers_1.RunnerType.Main;
function runMain() {
return __awaiter(this, void 0, void 0, function* () {
yield (0, index_1.run)(runner);
if (shouldRunMain()) {
yield (0, msdo_interface_1.getExecutor)(msdo_1.MicrosoftSecurityDevOps).runMain();
}
else {
console.log("Scanning is not enabled. Skipping...");
}
});
}
runMain().catch(error => {
core.setFailed(error);
});
function shouldRunMain() {
let toolsString = core.getInput('tools');
if (!common.isNullOrWhiteSpace(toolsString)) {
let tools = toolsString.split(',');
if (tools.length == 1 && tools[0].trim() == msdo_helpers_1.Tools.ContainerMapping) {
return false;
}
}
return true;
}
9 changes: 1 addition & 8 deletions lib/msdo-helpers.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.writeToOutStream = exports.getEncodedContent = exports.encode = exports.Constants = exports.Tools = exports.CommandType = exports.RunnerType = exports.Inputs = void 0;
exports.writeToOutStream = exports.getEncodedContent = exports.encode = exports.Constants = exports.Tools = exports.RunnerType = exports.Inputs = void 0;
const os_1 = __importDefault(require("os"));
var Inputs;
(function (Inputs) {
Expand All @@ -21,13 +21,6 @@ var RunnerType;
RunnerType["Pre"] = "pre";
RunnerType["Post"] = "post";
})(RunnerType || (exports.RunnerType = RunnerType = {}));
var CommandType;
(function (CommandType) {
CommandType["All"] = "all";
CommandType["PreJob"] = "pre-job";
CommandType["PostJob"] = "post-job";
CommandType["Run"] = "run";
})(CommandType || (exports.CommandType = CommandType = {}));
var Tools;
(function (Tools) {
Tools["Bandit"] = "bandit";
Expand Down
5 changes: 5 additions & 0 deletions lib/msdo-interface.js
Original file line number Diff line number Diff line change
@@ -1,2 +1,7 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.getExecutor = void 0;
function getExecutor(runner) {
return new runner();
}
exports.getExecutor = getExecutor;
Loading

0 comments on commit 7390911

Please sign in to comment.