-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Re-pushing the snyk-artifactory-upload tool
- Loading branch information
0 parents
commit a257418
Showing
23 changed files
with
2,355 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
name: Example workflow using Snyk | ||
on: | ||
push: | ||
branches: main | ||
|
||
env: | ||
PUBLISHER_ID: ${{ secrets.PUBLISHER_ID }} | ||
AZURE_TOKEN: ${{ secrets.AZURE_TOKEN }} | ||
|
||
jobs: | ||
develop: | ||
|
||
runs-on: ubuntu-latest | ||
steps: | ||
- uses: actions/checkout@v2 | ||
name: Extract Version number | ||
- id: set_version | ||
run: | | ||
content=`cat ./vss-extension.json` | ||
content="${content//'%'/'%25'}" | ||
content="${content//$'\n'/'%0A'}" | ||
content="${content//$'\r'/'%0D'}" | ||
echo "::set-output name=vssextensionjson::$content" | ||
name: Publish Visual Studio extension | ||
- run : | | ||
npm install -g tfx-cli | ||
npx tfx extension create --output-path --manifest-globs vss-extension.json | ||
npx tfx extension publish --auth-type pat -t $AZURE_TOKEN --publisher $PUBLISHER_ID --vsix ./SnykProfessionalServices.snyk-artifactory-upload-${{fromJson(steps.set_version.outputs.vssextensionjson).version}}.vsix |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
{ | ||
"$schema": "http://json.schemastore.org/vsix-publish", | ||
"categories": [ | ||
"build", | ||
"coding" | ||
], | ||
"identity": { | ||
"internalName": "snyk-artifactory-upload-test" | ||
}, | ||
"overview": "overview.md", | ||
"priceCategory": "free", | ||
"publisher": "SnykProfessionalServices", | ||
"private": true, | ||
"qna": true, | ||
"repo": "https://github.com/snyk-labs/snyk-artifactory-upload" | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
Copyright 2024 Snyk Ltd. | ||
|
||
Licensed under the Apache License, Version 2.0 (the "License"); | ||
you may not use this file except in compliance with the License. | ||
You may obtain a copy of the License at | ||
|
||
http://www.apache.org/licenses/LICENSE-2.0 | ||
|
||
Unless required by applicable law or agreed to in writing, software | ||
distributed under the License is distributed on an "AS IS" BASIS, | ||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
See the License for the specific language governing permissions and | ||
limitations under the License. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,101 @@ | ||
# Snyk Artifactory Upload | ||
|
||
## Overview | ||
|
||
This Azure DevOps task provides functionality to take Snyk vulnerability report details and upload them as properties onto Artifactory artifacts. It supports three main operations: `copy`, `process`, and `copyandprocess`. The task interacts with a Snyk vulnerability report file generated by a preceding task (Snyk Vulnerability Scan Task). | ||
|
||
## Features | ||
|
||
- **Copy Operation:** | ||
- Uploads the Snyk vulnerability report file to a user-specified directory (`snykFilePath` input). | ||
|
||
- **Process Operation:** | ||
- Retrieves the Snyk report from the specified directory (`snykFilePath` input). | ||
- Sets properties from the report file onto designated Artifactory artifacts. | ||
- Artifacts can be specified either by providing a list of artifact URLs or build details (build name, number, and project name). | ||
- When using the url list option you can call multiple URL's seperated by a delimter (which can be configured to be a custom in the task, by default it is <,>) | ||
- Url's can be specific artifacts or folders, the task will set properties as long as the path is valid. | ||
- Do not include initial slash in URL list, example of a valid list > "path/to/some/artifact, path/to/some/folder" | ||
|
||
## Usage | ||
|
||
### Parameters | ||
|
||
- **Operation:** | ||
- Choose one of the following operations: `copy`, `process`, `copyandprocess`. | ||
|
||
- **Snyk File Path (`snykFilePath`):** | ||
- The directory path where the Snyk vulnerability report file will be stored or retrieved. | ||
|
||
- **Artifact Specification:** | ||
- Specify artifacts either by providing a list of URLs or build details. | ||
|
||
### Example | ||
|
||
```yaml | ||
- task: snyk-artifactory-azure-upload@1 | ||
inputs: | ||
Operation: 'CopyAndProcess' | ||
SnykDirectory: '$(Pipeline.Workspace)' | ||
artifactoryServiceConnection: 'someserviceconnection' | ||
InputType: 'Build' | ||
BuildName: 'somebuild' | ||
BuildNumber: 'somebuildNumber' | ||
ProjectName: 'someProjectName' | ||
``` | ||
### Snyk Scan Data Properties | ||
Upon successfully retrieving scan data, the following properties are set on the artifact: | ||
- **Scan Status (`snyk_sast_scan_status`):** | ||
- Indicates the status of the Snyk Static Application Security Testing (SAST) scan. | ||
|
||
- **Findings Present (`snyk_sast_findings_present`):** | ||
- A boolean flag indicating whether Snyk findings are present. | ||
- `true` if findings are present, `false` otherwise. | ||
|
||
- **Highest Severity Level (`snyk_sast_highest_severity_level`):** | ||
- The highest severity level of vulnerabilities found in the scan. | ||
- Possible values: `"high"`, `"medium"`, `"low"`, etc. | ||
|
||
- **High Severity Count (`snyk_sast_high_severity_count`):** | ||
- The count of vulnerabilities with high severity. | ||
|
||
- **Medium Severity Count (`snyk_sast_medium_severity_count`):** | ||
- The count of vulnerabilities with medium severity. | ||
|
||
- **Low Severity Count (`snyk_sast_low_severity_count`):** | ||
- The count of vulnerabilities with low severity. | ||
|
||
- **Project Link (`snyk_sast_project_link`):** | ||
- A link to the Snyk project providing detailed information about the scan results. | ||
|
||
|
||
|
||
|
||
# Contributing to Azure DevOps Snyk Vulnerability Report Task | ||
|
||
Thank you for considering contributing to this project! Please take a moment to review the following guidelines. | ||
|
||
## Open Source Contributions | ||
|
||
We currently do not accept open source contributions, including pull requests. The development of this project is primarily maintained by the project owners. | ||
|
||
## Bug Reports and Feature Requests | ||
|
||
For bug reports or feature requests, please follow these steps: | ||
|
||
1. Check if the issue has already been reported in [GitHub Issues](https://github.com/snyk-labs/snyk-artifactory-upload/issues). | ||
2. If not, open a new issue. | ||
3. Provide detailed information about the problem or the requested feature. | ||
|
||
## Pull Requests | ||
|
||
As mentioned earlier, we do not accept open source contributions, including pull requests. However, we appreciate your interest in improving the project. | ||
|
||
Thank you for your understanding and support! | ||
|
||
## License | ||
|
||
By contributing, you agree that your contributions will be licensed under the [Apache License 2.0](./LICENSE). |
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
# Snyk Artifactory Upload | ||
|
||
## Overview | ||
|
||
This Azure DevOps task provides functionality to take Snyk vulnerability report details and upload them as properties onto Artifactory artifacts. It supports three main operations: `copy`, `process`, and `copyandprocess`. The task interacts with a Snyk vulnerability report file generated by a preceding task (Snyk Vulnerability Scan Task). | ||
|
||
## Features | ||
|
||
- **Copy Operation:** | ||
- Uploads the Snyk vulnerability report file to a user-specified directory (`snykFilePath` input). | ||
|
||
- **Process Operation:** | ||
- Retrieves the Snyk report from the specified directory (`snykFilePath` input). | ||
- Sets properties from the report file onto designated Artifactory artifacts. | ||
- Artifacts can be specified either by providing a list of artifact URLs or build details (build name, number, and project name). | ||
- When using the url list option you can call multiple URL's seperated by a delimter (which can be configured to be a custom in the task, by default it is <,>) | ||
- Url's can be specific artifacts or folders, the task will set properties as long as the path is valid. | ||
- Do not include initial slash in URL list, example of a valid list > "path/to/some/artifact, path/to/some/folder" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
node_modules | ||
.dccache |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
6aa09ff1-547d-437e-aa49-ea60f6b135e1 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,138 @@ | ||
"use strict"; | ||
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { | ||
if (k2 === undefined) k2 = k; | ||
var desc = Object.getOwnPropertyDescriptor(m, k); | ||
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { | ||
desc = { enumerable: true, get: function() { return m[k]; } }; | ||
} | ||
Object.defineProperty(o, k2, desc); | ||
}) : (function(o, m, k, k2) { | ||
if (k2 === undefined) k2 = k; | ||
o[k2] = m[k]; | ||
})); | ||
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { | ||
Object.defineProperty(o, "default", { enumerable: true, value: v }); | ||
}) : function(o, v) { | ||
o["default"] = v; | ||
}); | ||
var __importStar = (this && this.__importStar) || function (mod) { | ||
if (mod && mod.__esModule) return mod; | ||
var result = {}; | ||
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); | ||
__setModuleDefault(result, mod); | ||
return result; | ||
}; | ||
var __importDefault = (this && this.__importDefault) || function (mod) { | ||
return (mod && mod.__esModule) ? mod : { "default": mod }; | ||
}; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.setProperties = void 0; | ||
const tl = require("azure-pipelines-task-lib/task"); | ||
const axios_1 = __importDefault(require("axios")); | ||
const axios_retry_1 = __importDefault(require("axios-retry")); | ||
const Utils = __importStar(require("./helpers")); | ||
(0, axios_retry_1.default)(axios_1.default, { | ||
retries: 10, // Number of retries | ||
retryDelay: axios_retry_1.default.exponentialDelay, // Retry delay strategy | ||
onRetry: (retryCount, error, Config) => { console.log("Axios request failed with " + error + " retrying now.."); } | ||
}); | ||
function setProperties(properties) { | ||
var _a, _b; | ||
const inputType = (_a = tl.getInput("InputType", true)) === null || _a === void 0 ? void 0 : _a.toLowerCase(); | ||
// get username/password details from service connection | ||
const serviceConnectionId = tl.getInput('artifactoryServiceConnection', true); | ||
const auth = tl.getEndpointAuthorization(serviceConnectionId, false); | ||
let authType = tl.getEndpointAuthorizationScheme(serviceConnectionId, false); | ||
let authToken = ''; | ||
if (authType == 'UsernamePassword') { | ||
const username = auth === null || auth === void 0 ? void 0 : auth.parameters['username']; | ||
const password = auth === null || auth === void 0 ? void 0 : auth.parameters['password']; | ||
authToken = Buffer.from(`${username}:${password}`).toString('base64'); | ||
authType = 'Basic'; | ||
} | ||
else if (authType == 'Token') { | ||
authToken = auth === null || auth === void 0 ? void 0 : auth.parameters['apitoken']; | ||
authType = 'Bearer'; | ||
} | ||
const baseUrl = tl.getEndpointUrl(serviceConnectionId, true); | ||
//set API headers | ||
const headers = { | ||
Authorization: `${authType} ${authToken}`, | ||
'Content-Type': 'application/json', // Set content type based on your requirements | ||
}; | ||
//Retrieve artifact URLs | ||
let artifactUrls = []; | ||
if (inputType == "urllist") { | ||
const delimiter = tl.getInput('delimiter', false) || ','; | ||
artifactUrls = (_b = tl.getInput('artifactUrls', true)) === null || _b === void 0 ? void 0 : _b.split(delimiter); | ||
//add properties to each artifact | ||
for (let artifactUrlShort of artifactUrls) { | ||
artifactUrlShort = Utils.encodeUrl(artifactUrlShort); | ||
const artifactUrl = `${baseUrl}/api/storage/${artifactUrlShort}`; // Construct the complete URL | ||
Object.keys(properties).forEach((prop) => { | ||
const queryParams = { | ||
"properties": [prop] + '=' + properties[prop], // Assuming 'prop' and 'properties' are defined elsewhere | ||
}; | ||
axios_1.default.put(artifactUrl, null, { | ||
params: queryParams, | ||
headers: headers, | ||
}) | ||
.then(response => { | ||
console.log(`Successfully set property '${prop}' on Artifact ${artifactUrlShort}`); | ||
}) | ||
.catch(error => { | ||
//test | ||
console.log('Error while attempting to add property to Artifact:' + error); | ||
// Handle errors here | ||
process.exit(1); // Exiting with a non-zero code indicating an error | ||
}); | ||
}); | ||
} | ||
} | ||
else if (inputType == "build") { | ||
const buildName = tl.getInput('BuildName', true); | ||
const buildNumber = tl.getInput('BuildNumber', true); | ||
const projectName = tl.getInput('ProjectKey', true); | ||
const BuildStatus = tl.getInput('BuildStatus', false); | ||
const searchBody = Object.assign({ "buildName": buildName, "buildNumber": buildNumber, "project": projectName }, (BuildStatus !== null && { myProperty: BuildStatus })); | ||
const searchUrl = `${baseUrl}/api/search/buildArtifacts`; | ||
axios_1.default.post(searchUrl, JSON.stringify(searchBody), { | ||
headers: headers, | ||
}) | ||
.then((response) => { | ||
console.log("Data received from build search API: " + JSON.stringify(response.data)); | ||
artifactUrls = response.data.results.map((obj) => { | ||
const { downloadUri } = obj; | ||
const trimmedUrl = downloadUri.replace(`${baseUrl}/`, ""); | ||
return trimmedUrl; | ||
}); | ||
for (let artifactUrlShort of artifactUrls) { | ||
artifactUrlShort = Utils.encodeUrl(artifactUrlShort); | ||
const artifactUrl = `${baseUrl}/api/storage/${artifactUrlShort}`; // Construct the complete URL | ||
Object.keys(properties).forEach((prop) => { | ||
const queryParams = { | ||
"properties": [prop] + '=' + properties[prop], // Assuming 'prop' and 'properties' are defined elsewhere | ||
}; | ||
setTimeout(() => axios_1.default.put(artifactUrl, null, { | ||
params: queryParams, | ||
headers: headers, | ||
}) | ||
.then(response => { | ||
console.log(`Successfully set property '${prop}' on Artifact ${artifactUrlShort}`); | ||
// Adding a delay between each API call | ||
}) | ||
.catch(error => { | ||
console.log('Error while attempting to add property to Artifact: ' + error); | ||
// Handle errors here | ||
process.exit(1); // Exiting with a non-zero code indicating an error | ||
}), 1000); | ||
}); | ||
} | ||
}) | ||
.catch((error) => { | ||
console.error('Error from Artifactory search builds API:', error.response ? error.response.data : error.message); | ||
process.exit(1); | ||
}); | ||
} | ||
} | ||
exports.setProperties = setProperties; |
Oops, something went wrong.